package com.baiyue.lastleg.appointmentplanning; import org.springframework.stereotype.Service; import org.springframework.http.HttpStatus; import org.springframework.web.server.ResponseStatusException; import java.util.List; import java.util.Objects; import java.util.function.Function; import java.util.stream.Collectors; @Service public class AppointmentBatchPreviewService { private final AppointmentSourceService sources; private final AppointmentBatchPreviewMapper mapper; public AppointmentBatchPreviewService(AppointmentSourceService sources,AppointmentBatchPreviewMapper mapper) { this.sources=sources;this.mapper=mapper; } public record Preview(AppointmentPlanningPolicy.Group group,String originWarehouseName, String destinationWarehouseCode,String destinationTimezone,List sources, List missingFields) { } public Preview preview(List refs) { var resolved=sources.resolveBatch(refs); var ids=resolved.stream().map(AppointmentSourceService.Source::orderId).filter(Objects::nonNull).distinct().toList(); var flags=ids.isEmpty()?java.util.Map.of():mapper.flags(ids).stream() .collect(Collectors.toMap(AppointmentBatchPreviewMapper.Flags::orderId,Function.identity())); var cargo=resolved.stream().map(source->{ String reason=source.canFollowup()?null:String.join(";",source.blockReasons()); var state=source.orderId()==null?null:flags.get(source.orderId()); if(source.orderId()!=null && state==null) reason="货源已变化,请重新查询"; else if(state!=null) { if(state.detained()) reason="货物暂扣,请先处理后再合批"; else if(state.mixedDestinations()) reason="货物含多个目的地,请先核对明细"; else if(state.activeAppointment()) reason="货物已有有效预约,请编辑原预约"; } // Arrival/warehouse ETA is not a cargo-ready window. Until an authoritative producer exists it stays unknown. return new AppointmentPlanningPolicy.Cargo(source.sourceKey(),source.customerId(),source.originWarehouseId(), source.destinationKey(),"US","US",source.packages(),null,null,reason==null,reason); }).toList(); try { var group=AppointmentPlanningPolicy.group(cargo); return new Preview(group,resolved.get(0).originWarehouseName(),resolved.get(0).destinationWarehouseCode(), sources.destinationTimezone(resolved.get(0).destinationWarehouseCode()),resolved, group.unknownQuantitySources()>0?List.of("READY_WINDOW_UNVERIFIED","CARGO_QUANTITY_REVIEW"):List.of("READY_WINDOW_UNVERIFIED")); } catch(IllegalArgumentException error) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST,error.getMessage(),error); } } }