package ru.soune.nocopy.service.user; import jakarta.persistence.EntityNotFoundException; import lombok.AllArgsConstructor; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.soune.nocopy.dto.register.AccountType; import ru.soune.nocopy.dto.register.ChangePasswordRequest; import ru.soune.nocopy.dto.register.RegRequest; import ru.soune.nocopy.dto.tarriff.TariffInfoDTO; import ru.soune.nocopy.dto.user.UserDTO; import ru.soune.nocopy.dto.user.UserRequest; import ru.soune.nocopy.entity.company.Company; import ru.soune.nocopy.entity.tarif.Tariff; import ru.soune.nocopy.entity.tarif.TariffInfo; import ru.soune.nocopy.entity.tarif.TariffType; import ru.soune.nocopy.entity.user.Permission; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.CompanyAlreadyExist; import ru.soune.nocopy.exception.InvalidUserEmail; import ru.soune.nocopy.exception.NotValidationPasswordException; import ru.soune.nocopy.exception.UserNotFoundException; import ru.soune.nocopy.repository.CompanyRepository; import ru.soune.nocopy.repository.UserRepository; import ru.soune.nocopy.service.file.FileStatsService; import ru.soune.nocopy.service.tariff.TariffInfoService; import java.util.List; import java.util.Optional; @Service @AllArgsConstructor public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; private final FileStatsService fileStatsService; private final CompanyRepository companyRepository; private final TariffInfoService tariffInfoService; @Transactional public User changePassword(User user, ChangePasswordRequest request) { if (!passwordEncoder.matches(request.getCurrentPassword(), user.getPassword())) { throw new NotValidationPasswordException("Current password is incorrect"); } user.setPassword(passwordEncoder.encode(request.getNewPassword())); return userRepository.save(user); } public String userEmailById(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId)); return user.getEmail(); } @Transactional public UserDTO updateUser(UserRequest userRequest, User currentUser) { User user = userRepository.findById(currentUser.getId()) .orElseThrow(() -> new UserNotFoundException("User not found with id: " + currentUser.getId())); updateUserFromRequest(user, userRequest); User updatedUser = userRepository.save(user); return mapToDTO(updatedUser); } public UserDTO getUserInfo(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId)); return mapToDTO(user); } @Transactional public List getUsersCompanyEmails(String company) { return userRepository.emailsByCompany(company); } @Transactional public User activateAndVerifyUser(long userId) { Optional users = userRepository.findById(userId); User user = users.orElseThrow(() -> new UserNotFoundException("User not found with id: " + userId)); user.setActive(true); user.setEmailVerified(true); return userRepository.save(user); } @Transactional public User createUser(RegRequest registerRequest, boolean verified, Long createrId) { User user = new User(); user.setFullName(registerRequest.getFullName()); user.setEmail(registerRequest.getEmail()); user.setPassword(passwordEncoder.encode(registerRequest.getPassword())); user.setActive(!verified); user.setEmailVerified(!verified); AccountType accountType = AccountType.valueOf(registerRequest.getAccountType().toUpperCase()); if (accountType == AccountType.B2B && registerRequest.getCompanyName() != null) { try { createCompanyAccount(registerRequest, user); } catch (CompanyAlreadyExist exist) { throw new CompanyAlreadyExist("Company already exist"); } } else if (accountType == AccountType.B2C && registerRequest.getCompanyName() == null) { createIndividualAccount(user); } else { createIndividualCompanyAccount(user, createrId); } if (registerRequest.getPhone() != null) { user.setPhone(registerRequest.getPhone()); } return userRepository.save(user); } public Optional getUserById(Long userId) { return userRepository.findById(userId); } public boolean existsByEmailOrPhone(String email, String phone){ return userRepository.existsByEmail(email) || userRepository.existsByPhone(phone); } private void createCompanyAccount(RegRequest request, User user) { Optional byInn = companyRepository.findByInn(request.getInn()); if (byInn.isPresent()) { throw new CompanyAlreadyExist("Company was already created"); } Company company = new Company(); company.setCompanyName(request.getCompanyName()); company.setInn(request.getInn()); TariffInfo companyTariff = tariffInfoService.createTariffInfo(TariffType.DEMO); company.setTariffInfo(companyTariff); companyRepository.save(company); tariffInfoService.addTariffInfo(companyTariff); user.setCompany(company); user.grantPermission(Permission.COMPANY_ADMIN_PERMISSIONS); } private void createIndividualAccount(User user) { TariffInfo personalTariff = tariffInfoService.createTariffInfo(TariffType.DEMO); tariffInfoService.addTariffInfo(personalTariff); user.setPersonalTariffInfo(personalTariff); user.grantPermission(Permission.DEFAULT_USER_PERMISSIONS); } private void createIndividualCompanyAccount(User user, Long companyUserId) { User companyUser = getUserById(companyUserId).orElseThrow(() -> new EntityNotFoundException("Not found user id: " + companyUserId)); Company company = companyUser.getCompany(); if (company == null) { throw new IllegalStateException("Not have company"); } TariffInfo tariffInfo = company.getTariffInfo(); if (tariffInfo == null) { throw new IllegalStateException("Company not have tariff"); } user.setCompany(company); user.grantPermission(Permission.DEFAULT_USER_PERMISSIONS); } private void updateUserFromRequest(User user, UserRequest request) { if (request.getFullName() != null) { user.setFullName(request.getFullName()); } if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) { if (userRepository.existsByEmail(request.getEmail())) { throw new InvalidUserEmail("Email already exists: " + request.getEmail()); } user.setEmail(request.getEmail()); } if (request.getPhone() != null) { user.setPhone(request.getPhone()); } if (request.getGenderType() != null) { user.setGenderType(request.getGenderType()); } if (request.getBirthday() != null) { user.setBirthday(request.getBirthday()); } } private UserDTO mapToDTO(User user) { TariffInfo personalTariffInfo = user.getPersonalTariffInfo(); Tariff tariff = personalTariffInfo.getTariff(); Long fileOnDisk = user.canManageCompanySettings() ? fileStatsService.calculateCompanyFileSize(user.getId()): fileStatsService.calculateUserFileSize(user.getId()); Integer filesCount = user.canManageCompanySettings() ? fileStatsService.filesCompanyCount(user.getId()): fileStatsService.filesUserCount(user.getId()); TariffInfoDTO infoDTO = TariffInfoDTO.builder().tokens(personalTariffInfo.getTokens()) .id(personalTariffInfo.getId()) .tariffName(tariff.getName()) .status(personalTariffInfo.getStatus().name()) .tariffId(tariff.getId()) .currentFileCounts(filesCount) .maxFileCounts(tariff.getMaxFilesCount()) .currentFileOnDisk(fileOnDisk) .maxFileOnDisk(tariff.getDiskSize()) .startTariff(personalTariffInfo.getStartTariff()) .endTariff(personalTariffInfo.getEndTariff()) .tokens(personalTariffInfo.getTokens() + personalTariffInfo.getBoughtTokens()) .build(); return UserDTO.builder() .fullName(user.getFullName()) .company(user.getCompanyName()) .email(user.getEmail()) .active(user.isActive()) .phone(user.getPhone()) .genderType(user.getGenderType()) .birthday(user.getBirthday()) .createdAt(user.getCreatedAt()) .tariffInfo(infoDTO) .verifiedStatus(user.getVerificationStatus()) .build(); } }