SupplierService.java
package com.stocks.stockease.supplier;
import java.util.List;
import java.util.Optional;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.stocks.stockease.supplier.internal.SupplierRepository;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
/**
* Supplier module's public API for querying and mutating suppliers.
* Other modules depend on this service rather than reaching into the module's repository.
*/
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class SupplierService {
private final SupplierRepository supplierRepository;
private final ApplicationEventPublisher eventPublisher;
/**
* Finds a supplier by its ID.
*
* @param id supplier identifier
* @return the supplier, or empty if none exists with that ID
*/
public Optional<Supplier> findById(long id) {
return supplierRepository.findById(id);
}
/**
* Returns every live supplier.
*
* @return list of all suppliers that have not been soft-deleted
*/
public List<Supplier> findAll() {
return supplierRepository.findAll();
}
/**
* Creates and persists a new supplier.
*
* @param name supplier display name; must not be blank
* @param address supplier postal address; must not be blank
* @return the persisted supplier including its generated ID
* @throws IllegalArgumentException if name or address is missing or blank
*/
@Transactional
public Supplier create(String name, String address) {
requireNameAndAddress(name, address);
Supplier supplier = new Supplier();
supplier.setName(name);
supplier.setAddress(address);
return supplierRepository.save(supplier);
}
/**
* Updates a supplier's name and address.
*
* @param id supplier identifier
* @param name new display name; must not be blank
* @param address new postal address; must not be blank
* @return the updated supplier
* @throws EntityNotFoundException if no supplier exists with the given ID
* @throws IllegalArgumentException if name or address is missing or blank
*/
@Transactional
public Supplier update(long id, String name, String address) {
Supplier supplier = supplierRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Supplier with ID " + id + " not found."));
requireNameAndAddress(name, address);
supplier.setName(name);
supplier.setAddress(address);
return supplierRepository.save(supplier);
}
/**
* Soft-deletes a supplier, unless a listener vetoes the deletion.
*
* @param id supplier identifier
* @throws EntityNotFoundException if no supplier exists with the given ID
* @throws IllegalStateException if a listener vetoes the deletion, for instance because open
* invoices still reference the supplier
*/
@Transactional
public void deleteById(long id) {
Supplier supplier = supplierRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Supplier with ID " + id + " not found."));
// the event fires first so open-invoice vetoes abort before any state changes; a veto exception
// rolls back the transaction
eventPublisher.publishEvent(new SupplierDeletedEvent(supplier.getId(), supplier.getName()));
supplierRepository.delete(supplier);
}
/** Rejects a missing or blank name or address with the shared message. */
private static void requireNameAndAddress(String name, String address) {
if (name == null || name.isBlank() || address == null || address.isBlank()) {
throw new IllegalArgumentException("Supplier name and address are required.");
}
}
}