package com.izouma.nineth.service; import com.izouma.nineth.domain.*; import com.izouma.nineth.dto.CollectionDTO; import com.izouma.nineth.dto.CreateBlindBox; import com.izouma.nineth.dto.PageQuery; import com.izouma.nineth.dto.UserDTO; import com.izouma.nineth.enums.CollectionType; import com.izouma.nineth.exception.BusinessException; import com.izouma.nineth.repo.*; import com.izouma.nineth.utils.JpaUtils; import com.izouma.nineth.utils.SecurityUtils; import lombok.AllArgsConstructor; import org.apache.commons.collections.MapUtils; import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.transaction.Transactional; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Service @AllArgsConstructor public class CollectionService { private CollectionRepo collectionRepo; private LikeRepo likeRepo; private BlindBoxItemRepo blindBoxItemRepo; private AppointmentRepo appointmentRepo; private UserRepo userRepo; public Page all(PageQuery pageQuery) { pageQuery.getQuery().put("del", false); Specification specification = JpaUtils.toSpecification(pageQuery, Collection.class); specification = specification.and((Specification) (root, criteriaQuery, criteriaBuilder) -> { List and = new ArrayList<>(); if (!MapUtils.getString(pageQuery.getQuery(), "type", "").equals("BLIND_BOX")) { and.add(criteriaBuilder.notEqual(root.get("type"), CollectionType.BLIND_BOX)); } return criteriaBuilder.and(and.toArray(new Predicate[0])); }); return collectionRepo.findAll(specification, JpaUtils.toPageRequest(pageQuery)); } public Collection create(Collection record) { User minter = userRepo.findById(record.getMinterId()).orElse(SecurityUtils.getAuthenticatedUser()); record.setMinter(minter.getNickname()); record.setMinterId(minter.getId()); record.setMinterAvatar(minter.getAvatar()); record.setOwner(minter.getNickname()); record.setOwnerId(minter.getId()); record.setOwnerAvatar(minter.getAvatar()); record.setStock(record.getTotal()); record.setSale(0); return collectionRepo.save(record); } public CollectionDTO toDTO(Collection collection) { return toDTO(collection, true); } public CollectionDTO toDTO(Collection collection, boolean join) { CollectionDTO collectionDTO = new CollectionDTO(); BeanUtils.copyProperties(collection, collectionDTO); if (join) { if (SecurityUtils.getAuthenticatedUser() != null) { List list = likeRepo.findByUserIdAndCollectionId(SecurityUtils.getAuthenticatedUser().getId(), collection.getId()); collectionDTO.setLiked(!list.isEmpty()); if (collection.getType() == CollectionType.BLIND_BOX) { collectionDTO.setAppointment(appointmentRepo.findFirstByBlindBoxId(collection.getId()).isPresent()); } } } return collectionDTO; } public List toDTO(List collections) { List likes = new ArrayList<>(); List appointments = new ArrayList<>(); if (SecurityUtils.getAuthenticatedUser() != null) { likes.addAll(likeRepo.findByUserId(SecurityUtils.getAuthenticatedUser().getId())); appointments.addAll(appointmentRepo.findByUserId(SecurityUtils.getAuthenticatedUser().getId())); } return collections.stream().parallel().map(collection -> { CollectionDTO dto = toDTO(collection, false); if (!likes.isEmpty()) { dto.setLiked(likes.stream().anyMatch(l -> l.getCollectionId().equals(collection.getId()))); } if (!appointments.isEmpty()) { dto.setAppointment(appointments.stream().anyMatch(a -> a.getBlindBoxId().equals(collection.getId()))); } return dto; }).collect(Collectors.toList()); } public Page toDTO(Page collections) { List userDTOS = toDTO(collections.getContent()); return new PageImpl<>(userDTOS, collections.getPageable(), collections.getTotalElements()); } @Transactional public Collection createBlindBox(CreateBlindBox createBlindBox) { Collection blindBox = createBlindBox.getBlindBox(); List list = collectionRepo.findAllById(createBlindBox.getItems().stream().map(BlindBoxItem::getCollectionId) .collect(Collectors.toSet())); for (BlindBoxItem item : createBlindBox.getItems()) { Collection collection = list.stream().filter(i -> i.getId().equals(item.getCollectionId())).findAny() .orElseThrow(new BusinessException("所选藏品不存在")); if (item.getTotal() > collection.getStock()) { throw new BusinessException("所选藏品库存不足:" + collection.getName()); } } User user = userRepo.findById(blindBox.getMinterId()).orElse(SecurityUtils.getAuthenticatedUser()); blindBox.setMinter(user.getNickname()); blindBox.setMinterId(user.getId()); blindBox.setMinterAvatar(user.getAvatar()); blindBox.setOwner(user.getNickname()); blindBox.setOwnerId(user.getId()); blindBox.setOwnerAvatar(user.getAvatar()); blindBox.setStock(blindBox.getTotal()); blindBox.setSale(0); collectionRepo.save(blindBox); for (BlindBoxItem item : createBlindBox.getItems()) { Collection collection = list.stream().filter(i -> i.getId().equals(item.getCollectionId())).findAny() .orElseThrow(new BusinessException("所选藏品不存在")); collection.setStock(collection.getStock() - item.getTotal()); collectionRepo.save(collection); BlindBoxItem blindBoxItem = new BlindBoxItem(); BeanUtils.copyProperties(collection, blindBoxItem); blindBoxItem.setId(null); blindBoxItem.setCollectionId(item.getCollectionId()); blindBoxItem.setSale(0); blindBoxItem.setTotal(item.getTotal()); blindBoxItem.setStock(item.getTotal()); blindBoxItem.setRare(item.isRare()); blindBoxItem.setBlindBoxId(blindBox.getId()); blindBoxItemRepo.save(blindBoxItem); } return blindBox; } public void appointment(Long id, Long userId) { Collection collection = collectionRepo.findById(id).orElseThrow(new BusinessException("无记录")); if (collection.getType() != CollectionType.BLIND_BOX) { throw new BusinessException("非盲盒,无需预约"); } if (collection.getStartTime().isBefore(LocalDateTime.now())) { throw new BusinessException("盲盒已开售,无需预约"); } appointmentRepo.save(Appointment.builder() .userId(userId) .blindBoxId(id) .build()); } }