fix(dispatch): enforce confirmed FBA appointment before scheduling
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@ public interface AppointmentWorkDispatchPort {
|
||||
String departureBlockReason(String dispatchNo);
|
||||
record ReceivingWindow(String batchKey,String batchNo,String customerId,String destinationKey,String confirmationNo,
|
||||
java.time.Instant startAt,java.time.Instant endAt,String agreementKey,int version) { }
|
||||
/** 预排不受限;提交审核、审核通过和开始拣货须有真实收货确认及可执行时间。 */
|
||||
/** FBA选入前须已有正式时间确认;提交审核、审核通过和开始拣货继续复核运输安排。 */
|
||||
String reviewBlockReason(String dispatchNo,java.time.Instant plannedDepartureAt,java.time.Instant estimatedArrivalAt);
|
||||
List<ReceivingWindow> reviewEvidence(String dispatchNo);
|
||||
void removeItem(long dispatchId,long itemId);
|
||||
|
||||
+14
-5
@@ -25,16 +25,25 @@ public class AppointmentDispatchAvailability {
|
||||
&& a.members().stream().anyMatch(m->snapshot.batchKey().equals(m.batchKey()) && customer.equals(m.customerId()))).toList();
|
||||
if(agreements.size()!=1)return 0;
|
||||
var agreement=agreements.get(0);var details=agreement.details();
|
||||
if(details==null || !"SUCCESS".equals(details.appointmentStatus()) || details.appointmentAt()==null || !validTime(details.appointmentAt(),agreement.timezone(),details.startOffset()))return 0;
|
||||
if(details.appointmentEndAt()!=null && (!validTime(details.appointmentEndAt(),agreement.timezone(),details.endOffset()) || details.appointmentEndAt().isBefore(details.appointmentAt())))return 0;
|
||||
if(details==null || !"SUCCESS".equals(details.appointmentStatus()) || details.appointmentAt()==null)return 0;
|
||||
var start=confirmedInstant(details.appointmentAt(),agreement.timezone(),details.startOffset());
|
||||
if(start==null)return 0;
|
||||
if(details.appointmentEndAt()!=null) {
|
||||
var end=confirmedInstant(details.appointmentEndAt(),agreement.timezone(),details.endOffset());
|
||||
if(end==null || end.isBefore(start))return 0;
|
||||
}
|
||||
var members=agreement.members().stream().filter(m->snapshot.batchKey().equals(m.batchKey()) && customer.equals(m.customerId())).toList();
|
||||
if(members.size()!=1)return 0;
|
||||
var sources=members.get(0).sources().stream().filter(s->source.equals(s.sourceKey()) && destination.equals(s.destinationKey())).toList();
|
||||
return sources.size()==1?Math.max(0,sources.get(0).packageCount()):0;
|
||||
}
|
||||
/** 夏令时歧义须有明确偏移;不能把当地时间按服务器时区猜测。 */
|
||||
private boolean validTime(LocalDateTime at,String timezone,String offset) {
|
||||
try {var offsets=ZoneId.of(timezone).getRules().getValidOffsets(at);return offset==null?offsets.size()==1:offsets.contains(ZoneOffset.of(offset));}
|
||||
catch(DateTimeException|NullPointerException error){return false;}
|
||||
private Instant confirmedInstant(LocalDateTime at,String timezone,String offset) {
|
||||
try {
|
||||
var offsets=ZoneId.of(timezone).getRules().getValidOffsets(at);
|
||||
if(offsets.isEmpty() || offset==null && offsets.size()!=1)return null;
|
||||
var selected=offset==null?offsets.get(0):ZoneOffset.of(offset);
|
||||
return offsets.contains(selected)?at.toInstant(selected):null;
|
||||
} catch(DateTimeException|NullPointerException error){return null;}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user