🔹 허브 N row 생성 & 각 row 마다 배송담당자 배정
package chill_logistics.delivery_server.application;
import chill_logistics.delivery_server.application.dto.command.AssignedDeliveryPersonV1;
import chill_logistics.delivery_server.application.dto.command.HubRouteAfterCommandV1;
import chill_logistics.delivery_server.application.dto.command.HubRouteHubInfoV1;
import chill_logistics.delivery_server.domain.entity.DeliveryStatus;
import chill_logistics.delivery_server.domain.entity.FirmDelivery;
import chill_logistics.delivery_server.domain.entity.HubDelivery;
import chill_logistics.delivery_server.domain.repository.FirmDeliveryRepository;
import chill_logistics.delivery_server.domain.repository.HubDeliveryRepository;
import chill_logistics.delivery_server.presentation.ErrorCode;
import chill_logistics.delivery_server.presentation.dto.request.DeliveryCancelRequestV1;
import chill_logistics.delivery_server.presentation.dto.request.DeliveryStatusChangeRequestV1;
import java.util.List;
import java.util.UUID;
import lib.web.error.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@RequiredArgsConstructor
public class DeliveryCommandService {
private final HubDeliveryRepository hubDeliveryRepository;
private final FirmDeliveryRepository firmDeliveryRepository;
private final AsyncAiService asyncAiService;
private final DeliveryPersonAssignmentService deliveryPersonAssignmentService;
@Transactional
public void createHubDelivery(
HubRouteAfterCommandV1 message,
UUID segmentStartHubId,
String segmentStartHubName,
String segmentStartHubFullAddress,
UUID segmentEndHubId,
String segmentEndHubName,
String segmentEndHubFullAddress,
Integer expectedDeliveryDuration,
UUID hubDeliveryPersonId,
int deliverySequenceNum) {
log.info("[허브 배송 생성 시작] orderId={}, deliverySequenceNum={}",
message.orderId(), deliverySequenceNum);
DeliveryStatus deliveryStatus = DeliveryStatus.WAITING_FOR_HUB;
HubDelivery hubDelivery = HubDelivery.createFromSegment(
message,
segmentStartHubId,
segmentStartHubName,
segmentStartHubFullAddress,
segmentEndHubId,
segmentEndHubName,
segmentEndHubFullAddress,
expectedDeliveryDuration,
hubDeliveryPersonId,
deliverySequenceNum,
deliveryStatus
);
HubDelivery savedHubDelivery = hubDeliveryRepository.save(hubDelivery);
log.info("[허브 배송 생성 완료] hubDeliveryId={}, orderId={}, deliverySequenceNum={}",
savedHubDelivery.getId(),
savedHubDelivery.getOrderId(),
savedHubDelivery.getDeliverySequenceNum());
}
@Transactional
public void createFirmDelivery(
HubRouteAfterCommandV1 message,
UUID firmDeliveryPersonId,
int deliverySequenceNum) {
log.info("[업체 배송 생성 시작] orderId={}, deliverySequenceNum={}",
message.orderId(), deliverySequenceNum);
DeliveryStatus deliveryStatus = DeliveryStatus.MOVING_TO_FIRM;
List<HubRouteHubInfoV1> pathHubs = message.pathHubs();
if (pathHubs == null || pathHubs.isEmpty()) {
throw new BusinessException(ErrorCode.INVALID_HUB_ROUTE_PATH);
}
HubRouteHubInfoV1 lastHub = pathHubs.get(pathHubs.size() - 1);
UUID endHubId = lastHub.hubId();
FirmDelivery firmDelivery = FirmDelivery.createFrom(
message,
endHubId,
firmDeliveryPersonId,
deliverySequenceNum,
deliveryStatus
);
FirmDelivery savedFirmDelivery = firmDeliveryRepository.save(firmDelivery);
log.info("[업체 배송 생성 완료] firmDeliveryId={}, orderId={}, deliverySequenceNum={}",
savedFirmDelivery.getId(),
savedFirmDelivery.getOrderId(),
savedFirmDelivery.getDeliverySequenceNum());
}
@Transactional
public void createDelivery(HubRouteAfterCommandV1 message) {
log.info("[배송 생성 시작] orderId={}", message.orderId());
List<HubRouteHubInfoV1> pathHubs = message.pathHubs();
if (pathHubs == null || pathHubs.size() < 2) {
throw new BusinessException(ErrorCode.INVALID_HUB_ROUTE_PATH);
}
int hubSegmentCount = pathHubs.size() - 1;
log.info("[허브 구간 수 계산] orderId={}, hubSegmentCount={}", message.orderId(), hubSegmentCount);
UUID lastHubId = pathHubs.get(pathHubs.size() - 1).hubId();
AssignedDeliveryPersonV1 firmDeliveryPerson =
deliveryPersonAssignmentService.assignFirmDeliveryPerson(lastHubId);
UUID firmDeliveryPersonId = firmDeliveryPerson.userId();
String firstHubDeliveryPersonName = null;
for (int i = 0; i < hubSegmentCount; i++) {
int hubDeliverySequenceNum = i + 1;
Integer segmentExpectedDeliveryDuration =
(i == 0) ? message.expectedDeliveryDuration() : null;
HubRouteHubInfoV1 startHub = pathHubs.get(i);
HubRouteHubInfoV1 endHub = pathHubs.get(i + 1);
AssignedDeliveryPersonV1 hubDeliveryPerson =
deliveryPersonAssignmentService.assignHubDeliveryPerson(startHub.hubId());
UUID hubDeliveryPersonId = hubDeliveryPerson.userId();
String hubDeliveryPersonName = hubDeliveryPerson.userName();
if (i == 0) {
firstHubDeliveryPersonName = hubDeliveryPersonName;
}
createHubDelivery(
message,
startHub.hubId(),
startHub.hubName(),
startHub.hubFullAddress(),
endHub.hubId(),
endHub.hubName(),
endHub.hubFullAddress(),
segmentExpectedDeliveryDuration,
hubDeliveryPersonId,
hubDeliverySequenceNum
);
}
int firmDeliverySequenceNum = hubSegmentCount + 1;
createFirmDelivery(message, firmDeliveryPersonId, firmDeliverySequenceNum);
log.info(
"[배송 생성 완료 & 배송 담당자 배정 완료] orderId={}", message.orderId());
asyncAiService.sendDeadlineRequest(message, firstHubDeliveryPersonName);
}
@Transactional
public void changeDeliveryStatus(UUID deliveryId, DeliveryStatusChangeRequestV1 request) {
if (request.deliveryType() == DeliveryType.HUB) {
HubDelivery hubDelivery = getHubDeliveryByIdOrThrow(deliveryId);
hubDelivery.changeStatus(request.nextDeliveryStatus());
log.info("[허브 배송 상태 변경] deliveryId={}, nextDeliveryStatus={}",
deliveryId, request.nextDeliveryStatus());
}
if (request.deliveryType() == DeliveryType.FIRM) {
FirmDelivery firmDelivery = getFirmDeliveryByIdOrThrow(deliveryId);
firmDelivery.changeStatus(request.nextDeliveryStatus());
log.info("[업체 배송 상태 변경] deliveryId={}, nextDeliveryStatus={}",
deliveryId, request.nextDeliveryStatus());
}
}
@Transactional
public void cancelDelivery(UUID deliveryId, DeliveryCancelRequestV1 request) {
if (request.deliveryType() == DeliveryType.HUB) {
HubDelivery hubDelivery = getHubDeliveryByIdOrThrow(deliveryId);
hubDelivery.cancelDelivery();
log.info("[허브 배송 취소] deliveryId={}, orderId={}", deliveryId, hubDelivery.getOrderId());
}
if (request.deliveryType() == DeliveryType.FIRM) {
FirmDelivery firmDelivery = getFirmDeliveryByIdOrThrow(deliveryId);
firmDelivery.cancelDelivery();
log.info("[업체 배송 취소] deliveryId={}, orderId={}", deliveryId, firmDelivery.getOrderId());
}
}
private HubDelivery getHubDeliveryByIdOrThrow(UUID hubDeliveryId) {
return hubDeliveryRepository.findById(hubDeliveryId)
.orElseThrow(() -> new BusinessException(ErrorCode.HUB_DELIVERY_NOT_FOUND));
}
private FirmDelivery getFirmDeliveryByIdOrThrow(UUID firmDeliveryId) {
return firmDeliveryRepository.findById(firmDeliveryId)
.orElseThrow(() -> new BusinessException(ErrorCode.FIRM_DELIVERY_NOT_FOUND));
}
}