package ru.soune.nocopy.service; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.BindingResult; import org.springframework.validation.FieldError; import ru.soune.nocopy.entity.company.Company; import ru.soune.nocopy.entity.user.User; import ru.soune.nocopy.exception.ValidationException; import ru.soune.nocopy.exception.ResourceNotFoundException; import ru.soune.nocopy.handler.validator.RegRequestValidator; import ru.soune.nocopy.repository.CompanyRepository; import ru.soune.nocopy.repository.UserRepository; import java.time.LocalDateTime; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service @AllArgsConstructor @Slf4j public class CompanyService { private final CompanyRepository companyRepository; private final UserRepository userRepository; private final RegRequestValidator regRequestValidator; @Transactional(readOnly = true) public Company getCompanyById(String id) { return companyRepository.findById(id) .orElseThrow(() -> new ResourceNotFoundException("Company not found with id: " + id)); } @Transactional(readOnly = true) public Company getCompanyByName(String companyName) { return companyRepository.findByCompanyName(companyName) .orElseThrow(() -> new ResourceNotFoundException("Company not found with name: " + companyName)); } @Transactional(readOnly = true) public List getAllCompanies() { return companyRepository.findAll(); } @Transactional(readOnly = true) public Page getAllCompanies(Pageable pageable) { return companyRepository.findAll(pageable); } @Transactional(readOnly = true) public List searchCompaniesByName(String name) { return companyRepository.findByCompanyNameContainingIgnoreCase(name); } @Transactional public Company updateCompany(String id, String companyName, String phone, String address, String email) { Company company = getCompanyById(id); if (companyName != null) { company.setCompanyName(companyName); } if (phone != null) { company.setPhone(phone); } if (address != null) { company.setAddress(address); } if (email != null) { company.setEmail(email); } company.setUpdateDate(LocalDateTime.now()); validateCompanyData(company); return companyRepository.save(company); } @Transactional public Company addCompany(String companyName, String phone, String address, String email) { Company company = new Company(); company.setCompanyName(companyName); company.setPhone(phone); company.setAddress(address); company.setEmail(email); company.setRegisterDate(LocalDateTime.now()); validateCompanyData(company); return companyRepository.save(company); } @Transactional public void deleteCompany(String id) { List users = userRepository.findByCompanyId(id); users.forEach(user -> { user.setCompany(null); userRepository.save(user); }); companyRepository.deleteById(id); log.info("Company deleted: {}", id); } @Transactional(readOnly = true) public List getCompanyUsers(String companyId) { return userRepository.findByCompanyId(companyId); } @Transactional(readOnly = true) public long countCompanyUsers(String companyId) { return userRepository.countByCompanyId(companyId); } @Transactional public void addUserToCompany(String companyId, Long userId) { Company company = getCompanyById(companyId); User user = userRepository.findById(userId) .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); if (user.getCompany() != null) { throw new IllegalArgumentException("User already belongs to another company"); } user.setCompany(company); userRepository.save(user); log.info("User {} added to company {}", userId, companyId); } @Transactional public void addUserToCompany(Company company, User user) { if (user.getCompany() != null) { throw new IllegalArgumentException("User already belongs to another company"); } user.setCompany(company); userRepository.save(user); log.info("User {} added to company {}", user.getId(), company.getId()); } @Transactional public void deleteUserFromCompany(User user) { user.setCompany(null); userRepository.save(user); log.info("User {} removed from company", user.getId()); } @Transactional public void deleteUserFromCompany(Long userId) { User user = userRepository.findById(userId) .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + userId)); user.setCompany(null); userRepository.save(user); log.info("User {} removed from company", userId); } @Transactional(readOnly = true) public boolean companyExistsByName(String companyName) { return companyRepository.existsByCompanyName(companyName); } private void validateCompanyData(Company company) { BindingResult bindingResult = new BeanPropertyBindingResult(company, "company"); if (company.getCompanyName() != null) { regRequestValidator.validateCompanyName(company.getCompanyName(), bindingResult); } if (company.getEmail() != null) { regRequestValidator.validateEmail(company.getEmail(), bindingResult); } if (company.getPhone() != null) { regRequestValidator.validatePhone(company.getPhone(), bindingResult); } if (bindingResult.hasErrors()) { Map fieldErrors = bindingResult.getFieldErrors() .stream() .collect(Collectors.toMap( FieldError::getField, fieldError -> fieldError.getDefaultMessage() != null ? fieldError.getDefaultMessage() : "Validation error")); throw new ValidationException(bindingResult, null); } } }