fix(appointments): open canonical dispatch details from calendar
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package com.baiyue.lastleg.fleet.trip;
|
||||
|
||||
/** 日历专用只读查询投影,真实排车号不属于车次持久化字段。 */
|
||||
public class FleetTripCalendarRow extends FleetTripEntity {
|
||||
private String dispatchNo;
|
||||
|
||||
/** 返回关联整车主单的业务号。 */
|
||||
public String getDispatchNo() { return dispatchNo; }
|
||||
|
||||
/** 仅供日历SQL结果映射,不写入车次表。 */
|
||||
public void setDispatchNo(String dispatchNo) { this.dispatchNo = dispatchNo; }
|
||||
}
|
||||
+5
-4
@@ -11,10 +11,10 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
|
||||
/** Read-only transport plans. A trip is never evidence of a receiving appointment confirmation. */
|
||||
/** 排车日历沿真实整车主单读取运输时间,不代表已取得目的仓收货确认。 */
|
||||
@Service
|
||||
public class FleetTripCalendarService {
|
||||
public record Entry(String sourceType, String tripNo, String status, String originWarehouseId,
|
||||
public record Entry(String sourceType, String dispatchNo, String status, String originWarehouseId,
|
||||
String originWarehouseCode, String originWarehouseName, String originCountryCode,
|
||||
String originTimezone, String originWarehouseStatus, Instant plannedDepartureAt,
|
||||
Instant expectedDriverEndAt, Instant departedAt, Instant completedAt,
|
||||
@@ -31,12 +31,13 @@ public class FleetTripCalendarService {
|
||||
this.trips=trips; this.warehouses=warehouses; this.json=json; this.token=token;
|
||||
}
|
||||
|
||||
/** 一次读取真实排车及一次仓库资料查询,按业务地点判定日历归属。 */
|
||||
@Transactional(readOnly=true)
|
||||
public Result calendar(Instant from, Instant to) {
|
||||
if (from==null || to==null || !to.isAfter(from) || Duration.between(from,to).compareTo(Duration.ofDays(44))>0)
|
||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"查询须为不超过44天的UTC时间范围");
|
||||
var rows=trips.calendar(LocalDateTime.ofInstant(from,ZoneOffset.UTC),LocalDateTime.ofInstant(to,ZoneOffset.UTC));
|
||||
if (rows.size()>2000) throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"车次过多,请缩小查询日期范围");
|
||||
if (rows.size()>2000) throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"排车过多,请缩小查询日期范围");
|
||||
if (rows.isEmpty()) return new Result(List.of(),List.of());
|
||||
var ids=rows.stream().map(FleetTripEntity::getWarehouseId).filter(Objects::nonNull).filter(id->id>0).distinct().sorted().toList();
|
||||
var metadata=metadata(ids);
|
||||
@@ -60,7 +61,7 @@ public class FleetTripCalendarService {
|
||||
throw new IllegalArgumentException("incomplete route");
|
||||
stops=List.copyOf(stops);
|
||||
} catch (Exception invalid) { stops=List.of(); reasons.add("ROUTE_INCOMPLETE"); }
|
||||
var entry=new Entry("TRIP_PLAN",row.getTripNo(),row.getStatus(),row.getWarehouseId()==null?null:row.getWarehouseId().toString(),
|
||||
var entry=new Entry("DISPATCH",row.getDispatchNo(),row.getStatus(),row.getWarehouseId()==null?null:row.getWarehouseId().toString(),
|
||||
warehouse==null?row.getWarehouseCode():warehouse.warehouseCode(),warehouse==null?row.getWarehouseName():warehouse.warehouseName(),
|
||||
country,zone,warehouse==null?null:warehouse.status(),instant(row.getPlannedDepartureAt()),instant(row.getExpectedDriverEndAt()),
|
||||
instant(row.getDepartedAt()),instant(row.getCompletedAt()),stops,List.copyOf(reasons));
|
||||
|
||||
@@ -7,17 +7,18 @@ import org.apache.ibatis.annotations.Select;
|
||||
|
||||
@Mapper
|
||||
public interface FleetTripMapper extends BaseMapper<FleetTripEntity> {
|
||||
/** 预约日历只读海外仓出库派送,取货入仓车次不属于排车类型。 */
|
||||
/** 日历只读真实整车主单的出库派送,一单一条;独立车次及取消主单不进入排车日历。 */
|
||||
@Select("""
|
||||
SELECT trip_no,status,warehouse_id,warehouse_code,warehouse_name,planned_departure_at,
|
||||
expected_driver_end_at,departed_at,completed_at,stops_json
|
||||
FROM ll_fleet_trip
|
||||
WHERE trip_purpose='DELIVERY' AND (
|
||||
(departed_at IS NOT NULL AND departed_at>=#{from} AND departed_at<#{to})
|
||||
OR (departed_at IS NULL AND planned_departure_at>=#{from} AND planned_departure_at<#{to}))
|
||||
ORDER BY COALESCE(departed_at,planned_departure_at),trip_no LIMIT 2001
|
||||
SELECT d.dispatch_no,t.trip_no,t.status,t.warehouse_id,t.warehouse_code,t.warehouse_name,t.planned_departure_at,
|
||||
t.expected_driver_end_at,t.departed_at,t.completed_at,t.stops_json
|
||||
FROM ll_dispatch_order d JOIN ll_fleet_trip t ON t.id=d.trip_id
|
||||
WHERE d.status='ACTIVE' AND d.dispatch_no IS NOT NULL AND TRIM(d.dispatch_no)<>''
|
||||
AND t.trip_purpose='DELIVERY' AND (
|
||||
(t.departed_at IS NOT NULL AND t.departed_at>=#{from} AND t.departed_at<#{to})
|
||||
OR (t.departed_at IS NULL AND t.planned_departure_at>=#{from} AND t.planned_departure_at<#{to}))
|
||||
ORDER BY COALESCE(t.departed_at,t.planned_departure_at),d.dispatch_no LIMIT 2001
|
||||
""")
|
||||
java.util.List<FleetTripEntity> calendar(@Param("from") java.time.LocalDateTime from,@Param("to") java.time.LocalDateTime to);
|
||||
java.util.List<FleetTripCalendarRow> calendar(@Param("from") java.time.LocalDateTime from,@Param("to") java.time.LocalDateTime to);
|
||||
@Select("SELECT * FROM ll_fleet_trip WHERE trip_no=#{tripNo} FOR UPDATE")
|
||||
FleetTripEntity lockByNo(@Param("tripNo") String tripNo);
|
||||
@Select("SELECT * FROM ll_fleet_trip WHERE trip_no=#{tripNo}")
|
||||
|
||||
+3
-2
@@ -18,13 +18,14 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
@RequestMapping("/api/platform/v1/last-leg/fleet/trips")
|
||||
public class PlatformFleetTripController {
|
||||
@jakarta.annotation.Resource private FleetTripCalendarService calendar;
|
||||
/** 预约排车日历沿用真实排车列表读取权限,不要求已退出菜单的车次管理权限。 */
|
||||
@GetMapping("/calendar")
|
||||
@PreAuthorize("hasAuthority('platform:fleet:trip:list')")
|
||||
@PreAuthorize("hasAuthority('platform:overseas-warehouse:dispatch:list')")
|
||||
public ApiResponse<FleetTripCalendarService.Result> calendar(@AuthenticationPrincipal AuthenticatedUser user,
|
||||
@RequestParam java.time.Instant from,@RequestParam java.time.Instant to) {
|
||||
operator(user);
|
||||
if (!"PLATFORM".equals(user.appCode()) || !Long.valueOf(0).equals(user.tenantId()))
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN,"仅平台主体可读取车次日历");
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN,"仅平台主体可读取排车日历");
|
||||
return ApiResponse.success(calendar.calendar(from,to));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user