AssetServiceImpl.java
package com.nashtech.rookie.asset_management_0701.services.asset;
import java.time.LocalDate;
import java.util.List;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.nashtech.rookie.asset_management_0701.dtos.filters.AssetFilter;
import com.nashtech.rookie.asset_management_0701.dtos.requests.asset.AssetCreateDto;
import com.nashtech.rookie.asset_management_0701.dtos.requests.asset.AssetUpdateDto;
import com.nashtech.rookie.asset_management_0701.dtos.responses.PaginationResponse;
import com.nashtech.rookie.asset_management_0701.dtos.responses.asset.AssetResponseDto;
import com.nashtech.rookie.asset_management_0701.entities.Asset;
import com.nashtech.rookie.asset_management_0701.entities.Category;
import com.nashtech.rookie.asset_management_0701.entities.Location;
import com.nashtech.rookie.asset_management_0701.entities.User;
import com.nashtech.rookie.asset_management_0701.enums.EAssetState;
import com.nashtech.rookie.asset_management_0701.exceptions.AppException;
import com.nashtech.rookie.asset_management_0701.exceptions.ErrorCode;
import com.nashtech.rookie.asset_management_0701.mappers.AssetMapper;
import com.nashtech.rookie.asset_management_0701.repositories.AssetRepository;
import com.nashtech.rookie.asset_management_0701.repositories.AssignmentRepository;
import com.nashtech.rookie.asset_management_0701.repositories.CategoryRepository;
import com.nashtech.rookie.asset_management_0701.utils.PageSortUtil;
import com.nashtech.rookie.asset_management_0701.utils.asset_utils.AssetUtil;
import com.nashtech.rookie.asset_management_0701.utils.auth_util.AuthUtil;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AssetServiceImpl implements AssetService {
private final AssetRepository assetRepository;
private final AssetMapper assetMapper;
private final CategoryRepository categoryRepository;
private final AssignmentRepository assignmentRepository;
private final AuthUtil authUtil;
@Override
@Transactional
public AssetResponseDto createAsset (AssetCreateDto assetCreateDto) {
var category = categoryRepository
.findByName(assetCreateDto.getCategory())
.orElseThrow(() -> new AppException(ErrorCode.CATEGORY_NOT_FOUND));
validateInstallDate(assetCreateDto.getInstallDate());
Asset asset = assetMapper.toAsset(assetCreateDto);
asset.setCategory(category);
asset.setLocation(authUtil.getCurrentUser().getLocation());
asset.setAssetCode(AssetUtil.generateAssetCode(category.getCountAmount() + 1, category.getCode()));
category.setCountAmount(category.getCountAmount() + 1);
categoryRepository.save(category);
asset = assetRepository.save(asset);
return assetMapper.toAssetResponseDto(asset);
}
private void validateInstallDate (LocalDate installDate) {
LocalDate toThreeMonthsAgo = LocalDate.now().minusMonths(3);
if (installDate.isBefore(toThreeMonthsAgo)) {
throw new AppException(ErrorCode.ASSET_INSTALLED_DATE_TOO_OLD);
}
}
@Override
public PaginationResponse<AssetResponseDto> getAllAssets (AssetFilter assetFilter) {
Sort sort = Sort.by(PageSortUtil.parseSortDirection(assetFilter.getSortDir()), assetFilter.getOrderBy());
Pageable pageable = PageSortUtil.createPageRequest(assetFilter.getPageNumber()
, assetFilter.getPageSize(), sort);
Location currentLocation = authUtil.getCurrentUser().getLocation();
// check if the categoryIds are valid
List<Category> categories = categoryRepository.findAllById(assetFilter.getCategoryIds());
if (categories.size() != assetFilter.getCategoryIds().size()) {
throw new AppException(ErrorCode.CATEGORY_NOT_FOUND);
}
Page<Asset> assets = assetRepository.findAll(
Specification.where(AssetSpecification.hasAssetName(assetFilter.getSearchString()))
.or(AssetSpecification.hasAssetCode(assetFilter.getSearchString()))
.and(AssetSpecification.hasStates(assetFilter.getStates()))
.and(AssetSpecification.hasLocation(currentLocation))
.and(AssetSpecification.hasCategories(categories)),
pageable);
return PaginationResponse.<AssetResponseDto>builder()
.page(pageable.getPageNumber() + 1)
.total(assets.getTotalElements())
.itemsPerPage(pageable.getPageSize())
.data(assets.map(assetMapper::toAssetResponseDto).toList())
.build();
}
@Override
public AssetResponseDto getAssetById (Long id) {
Asset asset = assetRepository.findById(id)
.orElseThrow(() -> new AppException(ErrorCode.ASSET_NOT_FOUND));
return assetMapper.toAssetResponseDto(asset);
}
@Override
@Transactional
public void deleteAsset (Long id) {
Asset asset = assetRepository.findById(id)
.orElseThrow(() -> new AppException(ErrorCode.ASSET_NOT_FOUND));
if (assignmentRepository.existsByAssetId(id)) {
throw new AppException(ErrorCode.ASSET_WAS_ASSIGNED);
}
if (asset.getState().equals(EAssetState.ASSIGNED)) {
throw new AppException(ErrorCode.ASSET_IS_ASSIGNED);
}
assetRepository.delete(asset);
}
@Override
public boolean existAssignments (Long assetId) {
return assignmentRepository.existsByAssetId(assetId);
}
@Override
@Transactional
public AssetResponseDto updateAsset (Long id, AssetUpdateDto assetUpdateDto) {
Asset asset = assetRepository.findById(id)
.orElseThrow(() -> new AppException(ErrorCode.ASSET_NOT_FOUND));
if (!asset.getVersion().equals(assetUpdateDto.getVersion())) {
throw new AppException(ErrorCode.DATA_IS_OLD);
}
validateUpdateDate(asset.getInstallDate(), assetUpdateDto.getInstallDate());
User user = authUtil.getCurrentUser();
if (!asset.getLocation().equals(user.getLocation())) {
throw new AppException(ErrorCode.ASSET_NOT_FOUND);
}
if (asset.getState().equals(EAssetState.ASSIGNED)) {
throw new AppException(ErrorCode.ASSET_IS_ASSIGNED);
}
assetMapper.updateAsset(asset, assetUpdateDto);
try {
assetRepository.save(asset);
}
catch (OptimisticLockingFailureException e) {
throw new AppException(ErrorCode.DATA_IS_OLD);
}
return assetMapper.toAssetResponseDto(asset);
}
private void validateUpdateDate (LocalDate currInstalledDate, LocalDate installDate) {
LocalDate toThreeMonthsAgo = LocalDate.now().minusMonths(3);
if (installDate.isBefore(toThreeMonthsAgo) && installDate.isBefore(currInstalledDate)) {
throw new AppException(ErrorCode.ASSET_INSTALLED_DATE_TOO_OLD);
}
}
}