UpdateEquipmentService.java
package com.github.jenkaby.bikerental.equipment.application.service;
import com.github.jenkaby.bikerental.equipment.application.mapper.EquipmentCommandToDomainMapper;
import com.github.jenkaby.bikerental.equipment.application.usecase.UpdateEquipmentUseCase;
import com.github.jenkaby.bikerental.equipment.domain.exception.DuplicateSerialNumberException;
import com.github.jenkaby.bikerental.equipment.domain.exception.DuplicateUidException;
import com.github.jenkaby.bikerental.equipment.domain.model.Equipment;
import com.github.jenkaby.bikerental.equipment.domain.model.EquipmentType;
import com.github.jenkaby.bikerental.equipment.domain.repository.EquipmentRepository;
import com.github.jenkaby.bikerental.equipment.domain.repository.EquipmentTypeRepository;
import com.github.jenkaby.bikerental.equipment.domain.service.StatusTransitionPolicy;
import com.github.jenkaby.bikerental.equipment.shared.mapper.SerialNumberMapper;
import com.github.jenkaby.bikerental.equipment.shared.mapper.UidMapper;
import com.github.jenkaby.bikerental.shared.exception.ReferenceNotFoundException;
import com.github.jenkaby.bikerental.shared.exception.ResourceNotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
class UpdateEquipmentService implements UpdateEquipmentUseCase {
private final EquipmentRepository repository;
private final EquipmentCommandToDomainMapper mapper;
private final SerialNumberMapper serialNumberMapper;
private final UidMapper uidMapper;
private final EquipmentTypeRepository typeRepository;
private final StatusTransitionPolicy statusTransitionPolicy;
UpdateEquipmentService(
EquipmentRepository repository,
EquipmentCommandToDomainMapper mapper,
SerialNumberMapper serialNumberMapper,
UidMapper uidMapper,
EquipmentTypeRepository typeRepository,
StatusTransitionPolicy statusTransitionPolicy) {
this.repository = repository;
this.mapper = mapper;
this.serialNumberMapper = serialNumberMapper;
this.typeRepository = typeRepository;
this.uidMapper = uidMapper;
this.statusTransitionPolicy = statusTransitionPolicy;
}
@Override
@Transactional
public Equipment execute(UpdateEquipmentCommand command) {
var existing = repository.findById(command.id())
.orElseThrow(() -> new ResourceNotFoundException(Equipment.class.getSimpleName(), command.id().toString()));
var newSerial = serialNumberMapper.toSerialNumber(command.serialNumber());
if (!existing.getSerialNumber().equals(newSerial)) {
if (repository.existsBySerialNumber(newSerial)) {
throw new DuplicateSerialNumberException(Equipment.class, newSerial.value());
}
}
var newUid = uidMapper.toUid(command.uid());
if (!existing.getUid().equals(newUid)) {
if (repository.existsByUid(newUid)) {
throw new DuplicateUidException(Equipment.class, newUid.value());
}
}
String newType = command.typeSlug();
if (newType != null && !newType.equals(existing.getTypeSlug())) {
if (!typeRepository.existsBySlug(newType)) {
throw new ReferenceNotFoundException(EquipmentType.class, newType);
}
}
// validate status exists if changed
String newStatusSlug = command.statusSlug();
if (!newStatusSlug.equals(existing.getStatusSlug())) {
log.info("Changing status of equipment with id {} from {} to {}", existing.getId(), existing.getStatusSlug(), newStatusSlug);
existing.changeStatusTo(newStatusSlug, statusTransitionPolicy);
}
var updated = mapper.toEquipment(existing, command);
return repository.save(updated);
}
}