优化
This commit is contained in:
@@ -23,7 +23,7 @@ public interface WarehouseSupplierClient {
|
||||
@RequestParam String carrierCode);
|
||||
|
||||
record Snapshot(long supplierId, String name, String category, String status,
|
||||
List<String> carrierCodes) {}
|
||||
List<String> carrierCodes, String truckingScope) {}
|
||||
|
||||
@GetMapping("/{supplierId}/trucking-contact")
|
||||
ApiResponse<TruckingContact> truckingContact(@RequestHeader("X-Internal-Service-Token") String token,
|
||||
|
||||
@@ -92,12 +92,17 @@ public final class SmartLoadingDtos { private SmartLoadingDtos(){}
|
||||
Integer inboundFragmentCount,Integer fullPackageCount,List<Long> memberInboundIds) {
|
||||
public PlanCoLoadGroup { memberInboundIds=memberInboundIds==null?List.of():List.copyOf(memberInboundIds); }
|
||||
}
|
||||
public record PlanPalletMembers(Long palletId,List<GroupMemberCandidate> members) {
|
||||
public PlanPalletMembers { members=members==null?List.of():List.copyOf(members); }
|
||||
}
|
||||
public record Plan(Long id,String planNo,String status,Long bookingId,String containerNo,String voyageNo,
|
||||
Integer version,Boolean canAssign,Boolean canEdit,String blockedReason,String finalCompletionStatus,
|
||||
Long pdaTaskId,String pdaTaskStatus,Integer pdaTaskVersion,List<PlanCoLoadGroup> coLoadGroups,
|
||||
List<PlanPalletMembers> palletMembers,
|
||||
List<LoadingPlanItemEntity> items) {
|
||||
public Plan {
|
||||
coLoadGroups=coLoadGroups==null?List.of():List.copyOf(coLoadGroups);
|
||||
palletMembers=palletMembers==null?List.of():List.copyOf(palletMembers);
|
||||
items=items==null?List.of():List.copyOf(items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.apache.ibatis.annotations.*;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/** 一件代发逐箱清点、待绑托与封托事实。 */
|
||||
@@ -282,6 +283,21 @@ public interface DropshipPalletizationMapper {
|
||||
ORDER BY o.inbound_code,o.id
|
||||
""") List<GroupMemberCandidate> palletInboundMembers(@Param("palletId") long palletId);
|
||||
|
||||
@Select("""
|
||||
<script>
|
||||
SELECT c.pallet_id palletId,o.tenant_id accountId,o.id inboundId,o.order_id orderId,o.order_no orderNo,
|
||||
o.inbound_code inboundCode,o.customer_name customerName,COUNT(DISTINCT c.id) availablePackageCount,
|
||||
o.process_status orderStatusSnapshot,o.expected_arrival_at expectedArrivalAt
|
||||
FROM fl_dropship_pallet_carton c
|
||||
JOIN fl_inbound_order o ON o.id=c.inbound_id AND o.tenant_id=c.tenant_id
|
||||
WHERE c.pallet_id IN
|
||||
<foreach collection="palletIds" item="palletId" open="(" separator="," close=")">#{palletId}</foreach>
|
||||
GROUP BY c.pallet_id,o.tenant_id,o.id,o.order_id,o.order_no,o.inbound_code,o.customer_name,
|
||||
o.process_status,o.expected_arrival_at
|
||||
ORDER BY c.pallet_id,o.inbound_code,o.id
|
||||
</script>
|
||||
""") List<PlanPalletMemberRow> palletInboundMembersByPalletIds(@Param("palletIds") Collection<Long> palletIds);
|
||||
|
||||
@Select("""
|
||||
SELECT p.id pallet_id,p.pallet_no,'SEALED_PALLET' unit_type,TRUE indivisible,COUNT(DISTINCT c.id) carton_count,
|
||||
(SELECT COUNT(DISTINCT sku.sku_code) FROM fl_dropship_pallet_carton pc
|
||||
@@ -318,6 +334,7 @@ public interface DropshipPalletizationMapper {
|
||||
|
||||
@Getter @Setter class TaskRow { private Long id,tenantId,inboundId,warehouseId,assigneeId; private String inboundCode,customerName,warehouseName,taskStatus,assigneeName,processStatus,fulfillmentType; private Integer totalCartons,countedCartons,allocatedCartons,discrepancyCartons,expectedPalletCount,version; }
|
||||
@Getter @Setter class PalletRow { private Long id,taskId,tenantId,inboundId,warehouseId; private String palletNo,palletStatus,sealOperationId; private Integer version; private LocalDateTime completedAt; }
|
||||
@Getter @Setter class PlanPalletMemberRow { private Long palletId,accountId,inboundId,orderId; private String orderNo,inboundCode,customerName,orderStatusSnapshot; private Integer availablePackageCount; private LocalDateTime expectedArrivalAt; }
|
||||
@Getter @Setter class LabelRow { private Long cartonLabelId,inboundDetailId; private String skuCode,cargoName,inboundCode,boxCode; private Integer unitsPerCarton; }
|
||||
@Getter @Setter class LabelSkuRow { private Long inboundDetailId; private String skuCode,cargoName; private Integer expectedQuantity,lineNo; }
|
||||
@Getter @Setter class CartonRow { private Long id,taskId,palletId,inboundId,inboundDetailId; private String palletNo,inboundCode,skuCode,cargoName,boxCode,discrepancyStatus,discrepancyRemark; private Integer expectedSkuQuantity,actualSkuQuantity; }
|
||||
|
||||
@@ -149,7 +149,7 @@ public class ContainerService {
|
||||
validateSchedule(request.data());
|
||||
ContainerSpecificationCatalog.requireMatch(request.data().containerType(), request.data().capacityCbm(), request.data().maxWeightKg());
|
||||
WarehouseMasterDataClient.Warehouse warehouse = requireDomesticTransitWarehouse(request.data().warehouseId());
|
||||
var trucking = suppliers.trucking(request.data().terminalTruckingCompanyId(), request.data().terminalTruckingCompany());
|
||||
var trucking = suppliers.overseasTrucking(request.data().terminalTruckingCompanyId(), request.data().terminalTruckingCompany());
|
||||
copy(current, request.data());
|
||||
current.setWarehouseId(warehouse.id()); current.setWarehouseName(warehouse.warehouseName());
|
||||
current.setTerminalTruckingCompanyId(trucking == null ? null : trucking.supplierId());
|
||||
|
||||
@@ -1663,7 +1663,22 @@ public class SmartLoadingService {
|
||||
: "COMPLETED".equals(task.taskStatus()) ? "COMPLETED" : "IN_PROGRESS";
|
||||
return new Plan(p.getId(),p.getPlanNo(),p.getPlanStatus(),p.getContainerBookingId(),
|
||||
b.getContainerNo(),b.getVoyageNo(),p.getVersion(),mutable,mutable,blockedReason,finalStatus,
|
||||
task.taskId(),task.taskStatus(),task.taskVersion(),planCoLoadGroups(p.getId()),collapsePalletUnits(items));
|
||||
task.taskId(),task.taskStatus(),task.taskVersion(),planCoLoadGroups(p.getId()),planPalletMembers(items),
|
||||
collapsePalletUnits(items));
|
||||
}
|
||||
private List<PlanPalletMembers> planPalletMembers(List<LoadingPlanItemEntity> items) {
|
||||
List<Long> palletIds=items.stream().map(LoadingPlanItemEntity::getPalletId).filter(Objects::nonNull)
|
||||
.distinct().toList();
|
||||
if(palletIds.isEmpty()) return List.of();
|
||||
return dropshipPallets.palletInboundMembersByPalletIds(palletIds).stream()
|
||||
.collect(java.util.stream.Collectors.groupingBy(
|
||||
com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PlanPalletMemberRow::getPalletId,
|
||||
LinkedHashMap::new,java.util.stream.Collectors.toList()))
|
||||
.entrySet().stream().map(entry->new PlanPalletMembers(entry.getKey(),entry.getValue().stream()
|
||||
.map(row->new GroupMemberCandidate(row.getAccountId(),row.getInboundId(),row.getOrderId(),
|
||||
row.getOrderNo(),row.getInboundCode(),row.getCustomerName(),row.getAvailablePackageCount(),
|
||||
row.getOrderStatusSnapshot(),row.getExpectedArrivalAt()))
|
||||
.toList())).toList();
|
||||
}
|
||||
private List<LoadingPlanItemEntity> collapsePalletUnits(List<LoadingPlanItemEntity> items) {
|
||||
List<LoadingPlanItemEntity> result = new ArrayList<>();
|
||||
|
||||
@@ -34,7 +34,7 @@ public class TruckAppointmentFeeService {
|
||||
if (item == null || !"ACTIVE".equals(item.getStatus()) || !Boolean.TRUE.equals(item.getPickupPayable())) {
|
||||
throw conflict("国内拖车费项目不存在、已停用或未启用应付");
|
||||
}
|
||||
suppliers.trucking(appointment.getCarrierId(), null);
|
||||
suppliers.domesticTrucking(appointment.getCarrierId(), null);
|
||||
List<Share> shares = allocate(total, rows);
|
||||
Map<Long, List<Share>> plans = new LinkedHashMap<>();
|
||||
shares.forEach(share -> plans.computeIfAbsent(share.owner().planId(), ignored -> new ArrayList<>()).add(share));
|
||||
|
||||
@@ -47,8 +47,8 @@ public class TruckAppointmentService {
|
||||
@Transactional public TruckAppointmentAttachmentEntity upload(long id,String type,MultipartFile file,long uid){String attachmentType=attachmentType(type);required(id);try{var response=files.upload(internalToken,uid,0L,"TRUCK_APPOINTMENT_ATTACHMENT",Long.toString(id),file);if(response==null||!response.successful()||response.data()==null)throw bad("附件上传失败");var m=response.data();TruckAppointmentAttachmentEntity a=new TruckAppointmentAttachmentEntity();a.setId(IdWorker.getId());a.setAppointmentId(id);a.setFileId(m.fileId());a.setAttachmentType(attachmentType);a.setFileName(m.fileName());a.setFileHash(m.sha256());a.setVisibility("PLATFORM");a.setUploadedBy(uid);a.setUploadedAt(LocalDateTime.now());repo.attachment(a);return a;}catch(FeignException ex){throw new BizException(ResultCode.SERVICE_UNAVAILABLE,"文件服务暂不可用");}}
|
||||
@Transactional public TruckAppointmentAttachmentEntity attach(long id,AttachmentRequest r,long uid){String attachmentType=attachmentType(r.attachmentType());required(id);TruckAppointmentFileClient.Metadata metadata;try{var response=files.metadata(internalToken,0L,"TRUCK_APPOINTMENT_ATTACHMENT",Long.toString(id),r.fileId());if(response==null||!response.successful()||response.data()==null)throw bad("附件不存在或归属不匹配");metadata=response.data();}catch(FeignException ex){throw new BizException(ResultCode.SERVICE_UNAVAILABLE,"文件服务暂不可用");} TruckAppointmentAttachmentEntity a=new TruckAppointmentAttachmentEntity();a.setId(IdWorker.getId());a.setAppointmentId(id);a.setFileId(metadata.fileId());a.setAttachmentType(attachmentType);a.setFileName(metadata.fileName());a.setFileHash(metadata.sha256());a.setVisibility("PLATFORM");a.setUploadedBy(uid);a.setUploadedAt(LocalDateTime.now());repo.attachment(a);return a;}
|
||||
@Transactional public void deleteAttachment(long id,long attachmentId){required(id);if(repo.deleteAttachment(id,attachmentId)!=1)throw new BizException(ResultCode.NOT_FOUND,"附件引用不存在");}
|
||||
@Transactional public TruckAppointmentEntity create(long uid,String name,SaveRequest r){if(r.expectedVersion()==null||r.expectedVersion()!=0)throw bad("新增 expectedVersion 必须为0");validateRequired(r);completion.lockBooking(r.oceanBookingId());TruckAppointmentEntity active=repo.firstActiveForUpdate(r.oceanBookingId());if(active!=null)throw existingAppointmentConflict(active);AssociationContext links=validateAssociations(r);var carrier=suppliers.trucking(r.carrierId(),r.carrierName());TruckAppointmentEntity e=new TruckAppointmentEntity();e.setId(IdWorker.getId());e.setAppointmentNo(documentNumbers.next("TA"));e.setStatus(TruckAppointmentStatus.DRAFT);e.setRevision(0);e.setVersion(0);e.setCreatedAt(LocalDateTime.now());e.setUpdatedAt(e.getCreatedAt());copy(e,r,links,carrier.name());try{repo.insert(e);}catch(DuplicateKeyException exception){if(exception.getMessage()!=null&&exception.getMessage().contains("uk_truck_active_ocean_booking"))throw existingAppointmentConflict(repo.firstActiveForUpdate(r.oceanBookingId()));throw exception;}record(e,null,e.getStatus().name(),"CREATE",null,uid,name);completion.completeForBooking(e.getOceanBookingId());return enrich(required(e.getId()));}
|
||||
@Transactional public TruckAppointmentEntity edit(long id,long uid,String name,SaveRequest r){validateRequired(r);TruckAppointmentEntity e=required(id);completion.lockBooking(Math.min(e.getOceanBookingId(),r.oceanBookingId()));if(!Objects.equals(e.getOceanBookingId(),r.oceanBookingId()))completion.lockBooking(Math.max(e.getOceanBookingId(),r.oceanBookingId()));checkVersion(e,r.expectedVersion());if(!(e.getStatus()==TruckAppointmentStatus.DRAFT||e.getStatus()==TruckAppointmentStatus.PENDING_DISPATCH||e.getStatus()==TruckAppointmentStatus.RESCHEDULED))throw conflict("当前状态不可编辑");TruckAppointmentEntity active=repo.firstActiveForUpdate(r.oceanBookingId());if(active!=null&&!Objects.equals(active.getId(),e.getId()))throw existingAppointmentConflict(active);AssociationContext links=validateAssociations(r);var carrier=suppliers.trucking(r.carrierId(),r.carrierName());copy(e,r,links,carrier.name());try{if(repo.updateEdit(e,r.expectedVersion())!=1)throw conflict("版本已变化,请刷新后重试");}catch(DuplicateKeyException exception){if(exception.getMessage()!=null&&exception.getMessage().contains("uk_truck_active_ocean_booking"))throw existingAppointmentConflict(repo.firstActiveForUpdate(r.oceanBookingId()));throw exception;}record(e,e.getStatus().name(),e.getStatus().name(),"EDIT",null,uid,name);completion.completeForBooking(e.getOceanBookingId());return enrich(required(id));}
|
||||
@Transactional public TruckAppointmentEntity create(long uid,String name,SaveRequest r){if(r.expectedVersion()==null||r.expectedVersion()!=0)throw bad("新增 expectedVersion 必须为0");validateRequired(r);completion.lockBooking(r.oceanBookingId());TruckAppointmentEntity active=repo.firstActiveForUpdate(r.oceanBookingId());if(active!=null)throw existingAppointmentConflict(active);AssociationContext links=validateAssociations(r);var carrier=suppliers.domesticTrucking(r.carrierId(),r.carrierName());TruckAppointmentEntity e=new TruckAppointmentEntity();e.setId(IdWorker.getId());e.setAppointmentNo(documentNumbers.next("TA"));e.setStatus(TruckAppointmentStatus.DRAFT);e.setRevision(0);e.setVersion(0);e.setCreatedAt(LocalDateTime.now());e.setUpdatedAt(e.getCreatedAt());copy(e,r,links,carrier.name());try{repo.insert(e);}catch(DuplicateKeyException exception){if(exception.getMessage()!=null&&exception.getMessage().contains("uk_truck_active_ocean_booking"))throw existingAppointmentConflict(repo.firstActiveForUpdate(r.oceanBookingId()));throw exception;}record(e,null,e.getStatus().name(),"CREATE",null,uid,name);completion.completeForBooking(e.getOceanBookingId());return enrich(required(e.getId()));}
|
||||
@Transactional public TruckAppointmentEntity edit(long id,long uid,String name,SaveRequest r){validateRequired(r);TruckAppointmentEntity e=required(id);completion.lockBooking(Math.min(e.getOceanBookingId(),r.oceanBookingId()));if(!Objects.equals(e.getOceanBookingId(),r.oceanBookingId()))completion.lockBooking(Math.max(e.getOceanBookingId(),r.oceanBookingId()));checkVersion(e,r.expectedVersion());if(!(e.getStatus()==TruckAppointmentStatus.DRAFT||e.getStatus()==TruckAppointmentStatus.PENDING_DISPATCH||e.getStatus()==TruckAppointmentStatus.RESCHEDULED))throw conflict("当前状态不可编辑");TruckAppointmentEntity active=repo.firstActiveForUpdate(r.oceanBookingId());if(active!=null&&!Objects.equals(active.getId(),e.getId()))throw existingAppointmentConflict(active);AssociationContext links=validateAssociations(r);var carrier=suppliers.domesticTrucking(r.carrierId(),r.carrierName());copy(e,r,links,carrier.name());try{if(repo.updateEdit(e,r.expectedVersion())!=1)throw conflict("版本已变化,请刷新后重试");}catch(DuplicateKeyException exception){if(exception.getMessage()!=null&&exception.getMessage().contains("uk_truck_active_ocean_booking"))throw existingAppointmentConflict(repo.firstActiveForUpdate(r.oceanBookingId()));throw exception;}record(e,e.getStatus().name(),e.getStatus().name(),"EDIT",null,uid,name);completion.completeForBooking(e.getOceanBookingId());return enrich(required(id));}
|
||||
@Transactional
|
||||
public TruckAppointmentEntity action(long id,String action,ActionRequest r,String idem,String clientHash,long uid,String name){
|
||||
String requestHash=hash(action,id,r);verifyClientHash(clientHash,requestHash);
|
||||
|
||||
+15
-2
@@ -31,8 +31,21 @@ public class WarehouseSupplierSnapshotService {
|
||||
}
|
||||
}
|
||||
|
||||
public WarehouseSupplierClient.Snapshot trucking(Long supplierId, String suppliedName) {
|
||||
return resolve(supplierId, suppliedName, "TRUCKING");
|
||||
public WarehouseSupplierClient.Snapshot domesticTrucking(Long supplierId, String suppliedName) {
|
||||
return trucking(supplierId, suppliedName, "DOMESTIC");
|
||||
}
|
||||
|
||||
public WarehouseSupplierClient.Snapshot overseasTrucking(Long supplierId, String suppliedName) {
|
||||
return trucking(supplierId, suppliedName, "OVERSEAS");
|
||||
}
|
||||
|
||||
private WarehouseSupplierClient.Snapshot trucking(Long supplierId, String suppliedName, String scope) {
|
||||
var snapshot = resolve(supplierId, suppliedName, "TRUCKING");
|
||||
if (snapshot != null && !scope.equals(snapshot.truckingScope())) {
|
||||
throw new BizException(ResultCode.CONFLICT, "DOMESTIC".equals(scope)
|
||||
? "国内拖车只能使用国内拖车供应商" : "清关提柜只能使用海外车队");
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
public WarehouseSupplierClient.Snapshot customs(Long supplierId, String suppliedName) {
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ public class TerminalDrayageService {
|
||||
TerminalDrayageEntity value = mapper.lock(containerBookingId);
|
||||
requireVersion(value, request.expectedVersion());
|
||||
if (actualPickupAt(context, value) != null) throw conflict("实际提柜后不可更换码头车队");
|
||||
var fleet = suppliers.trucking(request.fleetSupplierId(), request.fleetSupplierName());
|
||||
var fleet = suppliers.overseasTrucking(request.fleetSupplierId(), request.fleetSupplierName());
|
||||
if (value != null && Objects.equals(value.getFleetSupplierId(), fleet.supplierId())) return view(context, value);
|
||||
if (value != null && value.getFleetSupplierId() != null) {
|
||||
mails.replaceFleet(containerBookingId, context.base().containerNo(), value.getFleetSupplierId(), fleet.supplierId(), operatorId);
|
||||
|
||||
@@ -1622,7 +1622,6 @@ components:
|
||||
lxCode: {type: string, nullable: true, description: 一件代发线路或履约产品编码快照}
|
||||
channelCode: {type: string, nullable: true}
|
||||
channelName: {type: string, nullable: true}
|
||||
fulfillmentType: {type: string, nullable: true, enum: [STANDARD, ONE_CLICK_DROPSHIP]}
|
||||
expectedPalletCount: {type: integer, minimum: 1, maximum: 1000, nullable: true, description: 一件代发预计托数;测量审核通过后按此数量预生成 DP 托盘码}
|
||||
taxMode: {type: string, nullable: true}
|
||||
pricingTaxMode: {type: string, nullable: true}
|
||||
@@ -2445,19 +2444,20 @@ components:
|
||||
groupMembers:
|
||||
type: array
|
||||
description: 同柜组或封托托盘的完整入仓成员;SEALED_PALLET 行按托盘唯一分页,成员 availablePackageCount 为该入仓码在本托的箱数,行 availablePackageCount 为整托总箱数。搜索命中任一成员仍返回整托完整组成;普通箱件候选为空数组。
|
||||
items:
|
||||
type: object
|
||||
required: [accountId, inboundId, orderId, orderNo, inboundCode, customerName, availablePackageCount]
|
||||
properties:
|
||||
accountId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
orderNo: {type: string}
|
||||
inboundCode: {type: string}
|
||||
customerName: {type: string}
|
||||
availablePackageCount: {type: integer, minimum: 0}
|
||||
orderStatusSnapshot: {type: string, nullable: true}
|
||||
expectedArrivalAt: {type: string, format: date-time, nullable: true}
|
||||
items: {$ref: '#/components/schemas/SmartLoadingCandidateGroupMember'}
|
||||
SmartLoadingCandidateGroupMember:
|
||||
type: object
|
||||
required: [accountId, inboundId, orderId, orderNo, inboundCode, customerName, availablePackageCount]
|
||||
properties:
|
||||
accountId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
orderId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
orderNo: {type: string}
|
||||
inboundCode: {type: string}
|
||||
customerName: {type: string}
|
||||
availablePackageCount: {type: integer, minimum: 0}
|
||||
orderStatusSnapshot: {type: string, nullable: true}
|
||||
expectedArrivalAt: {type: string, format: date-time, nullable: true}
|
||||
SmartLoadingWorkbenchContainerPageEnvelope:
|
||||
type: object
|
||||
required: [code, message, data]
|
||||
@@ -2496,7 +2496,7 @@ components:
|
||||
version: {type: integer, minimum: 0, description: 柜次版本}
|
||||
SmartLoadingPlan:
|
||||
type: object
|
||||
required: [id, planNo, status, bookingId, version, canAssign, canEdit, finalCompletionStatus, coLoadGroups, items]
|
||||
required: [id, planNo, status, bookingId, version, canAssign, canEdit, finalCompletionStatus, coLoadGroups, palletMembers, items]
|
||||
properties:
|
||||
id: {type: string}
|
||||
planNo: {type: string, pattern: '^LP-[0-9]{6}-[0-9]{4}$', example: LP-260818-0001, description: 预装与确认装柜清单共用的稳定编号}
|
||||
@@ -2516,6 +2516,10 @@ components:
|
||||
type: array
|
||||
description: 当前计划内同柜不可拆组的完整冻结快照;随计划一次返回,调用方不得按 inboundId 扇出重建
|
||||
items: {$ref: '#/components/schemas/SmartLoadingPlanCoLoadGroup'}
|
||||
palletMembers:
|
||||
type: array
|
||||
description: 当前计划内每个整托按入仓码汇总的实际装柜箱数;用于一托一行时展示完整组成
|
||||
items: {$ref: '#/components/schemas/SmartLoadingPlanPalletMembers'}
|
||||
items:
|
||||
type: array
|
||||
items: {$ref: '#/components/schemas/SmartLoadingPlanItem'}
|
||||
@@ -2534,6 +2538,15 @@ components:
|
||||
minItems: 1
|
||||
uniqueItems: true
|
||||
items: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
SmartLoadingPlanPalletMembers:
|
||||
type: object
|
||||
required: [palletId, members]
|
||||
properties:
|
||||
palletId: {type: string, pattern: '^[1-9][0-9]*$'}
|
||||
members:
|
||||
type: array
|
||||
minItems: 1
|
||||
items: {$ref: '#/components/schemas/SmartLoadingCandidateGroupMember'}
|
||||
SmartLoadingPlanItem:
|
||||
type: object
|
||||
required: [id, packageCount, totalPackageCount, remainingPackageCount, version, pickedPackageCount, minPackageCount, canAdjust, canRemove]
|
||||
|
||||
@@ -109,7 +109,7 @@ components:
|
||||
required: [expectedVersion, fleetSupplierId]
|
||||
properties:
|
||||
expectedVersion: {type: integer, minimum: 0}
|
||||
fleetSupplierId: {type: string, pattern: '^[1-9][0-9]*$', description: Warehouse ACTIVE/TRUCKING供应商ID}
|
||||
fleetSupplierId: {type: string, pattern: '^[1-9][0-9]*$', description: Warehouse ACTIVE/TRUCKING且truckingScope=OVERSEAS的海外车队供应商ID}
|
||||
fleetSupplierName: {type: string, maxLength: 128, nullable: true, description: 可选一致性提示,持久化名称以服务端快照为准}
|
||||
reason: {type: string, maxLength: 500, nullable: true}
|
||||
PickupAppointmentRequest:
|
||||
|
||||
@@ -223,7 +223,7 @@ components:
|
||||
outboundOrderId: {type: integer, format: int64, minimum: 1, nullable: true}
|
||||
oceanBookingId: {type: integer, format: int64, minimum: 1, description: Required RELEASED booking; must have a bill of lading and own an active BOOKING_CONFIRMATION or BILL_OF_LADING file.}
|
||||
warehouseId: {type: integer, format: int64, minimum: 1, nullable: true, description: Optional consistency hint. The persisted warehouse is frozen from the selected booking.}
|
||||
carrierId: {type: integer, format: int64, minimum: 1, description: Required ACTIVE Warehouse supplier ID validated as TRUCKING.}
|
||||
carrierId: {type: integer, format: int64, minimum: 1, description: Required ACTIVE Warehouse supplier ID validated as TRUCKING with truckingScope DOMESTIC (国内拖车).}
|
||||
carrierName: {type: string, maxLength: 128, nullable: true, description: Optional consistency hint only; the persisted snapshot comes from Warehouse supplier master data.}
|
||||
billOfLadingNo: {type: string, maxLength: 128, nullable: true, description: Optional consistency hint; the persisted snapshot is always frozen from the selected RELEASED booking.}
|
||||
plannedLoadingAt: {type: string, format: date-time}
|
||||
|
||||
+6
-6
@@ -92,7 +92,7 @@ class OceanBookingServiceTest {
|
||||
private void saveAndReleaseWithoutCustomer(boolean initialCustomer) throws Exception {
|
||||
stubMasterData();
|
||||
when(suppliers.booking(81L, "订舱代理")).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("MATSON")));
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("MATSON"), null));
|
||||
var tree = objectMapper.valueToTree(completeDraft());
|
||||
((com.fasterxml.jackson.databind.node.ObjectNode) tree).putNull("customerId").putNull("customerName");
|
||||
DraftData emptyCustomer = objectMapper.treeToValue(tree, DraftData.class);
|
||||
@@ -243,7 +243,7 @@ class OceanBookingServiceTest {
|
||||
|
||||
stubMasterData();
|
||||
when(suppliers.booking(81L, null)).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("SML")));
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("SML"), null));
|
||||
assertThatThrownBy(() -> service.create(9L, "admin", "agent-mismatch",
|
||||
new CreateRequest(0, completeDraft())))
|
||||
.isInstanceOf(BizException.class).hasMessage("所选订舱代理未关联当前船公司");
|
||||
@@ -253,8 +253,8 @@ class OceanBookingServiceTest {
|
||||
@Test
|
||||
void bookingAgentCandidatesAreFilteredByCarrierCode() {
|
||||
when(suppliers.bookingCandidates("MATSON")).thenReturn(List.of(
|
||||
new WarehouseSupplierClient.Snapshot(81L, "匹配代理", "BOOKING", "ACTIVE", List.of("MATSON")),
|
||||
new WarehouseSupplierClient.Snapshot(82L, "不匹配代理", "BOOKING", "ACTIVE", List.of("SML"))));
|
||||
new WarehouseSupplierClient.Snapshot(81L, "匹配代理", "BOOKING", "ACTIVE", List.of("MATSON"), null),
|
||||
new WarehouseSupplierClient.Snapshot(82L, "不匹配代理", "BOOKING", "ACTIVE", List.of("SML"), null)));
|
||||
|
||||
assertThat(service.bookingAgents("matson")).extracting(BookingAgentOption::name)
|
||||
.containsExactly("匹配代理");
|
||||
@@ -268,7 +268,7 @@ class OceanBookingServiceTest {
|
||||
when(repository.parties(1L)).thenReturn(parties());
|
||||
when(repository.requirements(1L)).thenReturn(List.of(requirement()));
|
||||
when(suppliers.booking(81L, null)).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("SML")));
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("SML"), null));
|
||||
|
||||
assertThatThrownBy(() -> service.release(1L, 9L, "admin", "release-agent-mismatch",
|
||||
new ReleaseRequest(3, "确认")))
|
||||
@@ -392,7 +392,7 @@ class OceanBookingServiceTest {
|
||||
new WarehouseMasterDataClient.Detail(new WarehouseMasterDataClient.Warehouse(
|
||||
701L, 0L, "SZX", null, "深圳中转仓", "DOMESTIC", "ACTIVE"))));
|
||||
when(suppliers.booking(81L, null)).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("MATSON")));
|
||||
new WarehouseSupplierClient.Snapshot(81L, "订舱代理", "BOOKING", "ACTIVE", List.of("MATSON"), null));
|
||||
when(partners.active(any(), eq(0L), eq(71L))).thenReturn(ApiResponse.success(
|
||||
new com.baiyue.firstleg.client.WarehousePartnerClient.Snapshot(71L, 0L, "船公司", "CARRIER",
|
||||
"MATSON", List.of("CARRIER"), "ACTIVE")));
|
||||
|
||||
+7
@@ -9,6 +9,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baiyue.firstleg.dto.SmartLoadingDtos.WorkbenchContainerQuery;
|
||||
import com.baiyue.firstleg.dto.SmartLoadingDtos.InboundCandidateQuery;
|
||||
@@ -34,6 +35,12 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
.contains("WHERE c.pallet_id=#{palletId}")
|
||||
.contains("GROUP BY o.tenant_id,o.id")
|
||||
.doesNotContain("#{inboundId}");
|
||||
String planMembers = String.join(" ", com.baiyue.firstleg.mapper.DropshipPalletizationMapper.class
|
||||
.getDeclaredMethod("palletInboundMembersByPalletIds", Collection.class)
|
||||
.getAnnotation(Select.class).value());
|
||||
assertThat(planMembers).contains("COUNT(DISTINCT c.id) availablePackageCount")
|
||||
.contains("<foreach collection=\"palletIds\"")
|
||||
.contains("GROUP BY c.pallet_id,o.tenant_id,o.id");
|
||||
}
|
||||
@Test
|
||||
void candidateHasOnlyTheCanonicalMybatisConstructor() {
|
||||
|
||||
+1
-1
@@ -220,7 +220,7 @@ class ContainerFeeDetailServiceTest {
|
||||
when(feeItems.findItem(11L)).thenReturn(item());
|
||||
when(suppliers.fee(71L, null)).thenReturn(
|
||||
new com.baiyue.firstleg.client.WarehouseSupplierClient.Snapshot(
|
||||
71L, "现有供应商", "TRUCKING", "ACTIVE", List.of()));
|
||||
71L, "现有供应商", "TRUCKING", "ACTIVE", List.of(), "DOMESTIC"));
|
||||
LocalDateTime paidAt = LocalDateTime.of(2026, 8, 20, 10, 0);
|
||||
var request = new ContainerFeeDetailDtos.SaveRequest(11L, "PAYABLE",
|
||||
LocalDate.of(2026, 8, 20), new BigDecimal("300.00"), "CNY", 71L,
|
||||
|
||||
@@ -57,11 +57,11 @@ class ContainerServiceTest {
|
||||
when(smartLoadingService.createForContainer(anyLong(), anyLong(), anyString())).thenAnswer(invocation ->
|
||||
new com.baiyue.firstleg.dto.SmartLoadingDtos.Plan(501L, "LP-260818-0001", "EDITING",
|
||||
invocation.getArgument(0, Long.class), null, null, 0, true, true, null,
|
||||
"NOT_STARTED", null, null, null, List.of(), List.of()));
|
||||
"NOT_STARTED", null, null, null, List.of(), List.of(), List.of()));
|
||||
when(warehouses.active(anyString(), anyLong(), anyLong())).thenAnswer(invocation ->
|
||||
activeWarehouse(invocation.getArgument(2, Long.class), "DOMESTIC", "上海中转仓"));
|
||||
when(suppliers.trucking(202L, "拖车公司A"))
|
||||
.thenReturn(new WarehouseSupplierClient.Snapshot(202L, "拖车公司A", "TRUCKING", "ACTIVE", List.of()));
|
||||
when(suppliers.overseasTrucking(202L, "拖车公司A"))
|
||||
.thenReturn(new WarehouseSupplierClient.Snapshot(202L, "拖车公司A", "TRUCKING", "ACTIVE", List.of(), "OVERSEAS"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -159,6 +159,40 @@ class SmartLoadingServiceTest {
|
||||
verify(coloadGroups,never()).findByInbound(anyLong(),anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsEveryInboundCompositionWhenAPlanCollapsesASealedPalletToOneRow() {
|
||||
LoadingPlanEntity plan = plan("EDITING", 2);
|
||||
when(repository.plan(1L)).thenReturn(plan);
|
||||
when(repository.booking(99L)).thenReturn(booking());
|
||||
LoadingPlanItemEntity first=item(101L,1L,201L,6);
|
||||
first.setInboundId(180L); first.setOrderId(280L); first.setOrderNo("O180"); first.setInboundCode("I180");
|
||||
first.setCustomerName("客户"); first.setPalletId(801L); first.setPalletNo("DP-0025"); first.setUnitType("SEALED_PALLET");
|
||||
LoadingPlanItemEntity second=item(102L,1L,202L,5);
|
||||
second.setInboundId(181L); second.setOrderId(281L); second.setOrderNo("O181"); second.setInboundCode("I181");
|
||||
second.setCustomerName("客户"); second.setPalletId(801L); second.setPalletNo("DP-0025"); second.setUnitType("SEALED_PALLET");
|
||||
when(repository.items(1L)).thenReturn(List.of(first,second));
|
||||
var firstMember=new com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PlanPalletMemberRow();
|
||||
firstMember.setPalletId(801L); firstMember.setAccountId(1L); firstMember.setInboundId(180L);
|
||||
firstMember.setOrderId(280L); firstMember.setOrderNo("O180"); firstMember.setInboundCode("I180");
|
||||
firstMember.setCustomerName("客户"); firstMember.setAvailablePackageCount(6);
|
||||
var secondMember=new com.baiyue.firstleg.mapper.DropshipPalletizationMapper.PlanPalletMemberRow();
|
||||
secondMember.setPalletId(801L); secondMember.setAccountId(1L); secondMember.setInboundId(181L);
|
||||
secondMember.setOrderId(281L); secondMember.setOrderNo("O181"); secondMember.setInboundCode("I181");
|
||||
secondMember.setCustomerName("客户"); secondMember.setAvailablePackageCount(5);
|
||||
when(dropshipPallets.palletInboundMembersByPalletIds(List.of(801L)))
|
||||
.thenReturn(List.of(firstMember,secondMember));
|
||||
|
||||
Plan result=service.detail(1L);
|
||||
|
||||
assertThat(result.items()).singleElement().satisfies(row->assertThat(row.getPackageCount()).isEqualTo(11));
|
||||
assertThat(result.palletMembers()).singleElement().satisfies(pallet->{
|
||||
assertThat(pallet.palletId()).isEqualTo(801L);
|
||||
assertThat(pallet.members()).extracting(GroupMemberCandidate::inboundCode).containsExactly("I180","I181");
|
||||
assertThat(pallet.members()).extracting(GroupMemberCandidate::availablePackageCount).containsExactly(6,5);
|
||||
});
|
||||
verify(dropshipPallets).palletInboundMembersByPalletIds(List.of(801L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void restoresLoadingPlanForContinuedAssignment() {
|
||||
LoadingPlanEntity plan = plan("LOADING", 3);
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ class TruckAppointmentFeeServiceTest {
|
||||
assertThat(request.getValue().fee().remark()).contains("TA-260914-0111");
|
||||
assertThat(request.getValue().fee().businessDate()).isEqualTo(DEPARTED.toLocalDate());
|
||||
assertThat(request.getValue().allocations().get(0).amount()).isEqualByComparingTo("100");
|
||||
verify(suppliers).trucking(8L, null);
|
||||
verify(suppliers).domesticTrucking(8L, null);
|
||||
verify(containers).approveAllocationGroup(10L, 500L, 0L, "系统(拖车离仓完成)");
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -43,8 +43,8 @@ class TruckAppointmentPayableFlowTest {
|
||||
item.setFeeTypeName("拖车费"); item.setStatus("ACTIVE"); item.setPickupPayable(true); item.setSupplierCategory("TRUCKING");
|
||||
when(items.findItemByCode("FEE_TYPE_108")).thenReturn(item);
|
||||
when(items.findItem(108L)).thenReturn(item);
|
||||
var supplier = new WarehouseSupplierClient.Snapshot(8L, "测试车队", "TRUCKING", "ACTIVE", List.of());
|
||||
when(suppliers.trucking(8L, null)).thenReturn(supplier);
|
||||
var supplier = new WarehouseSupplierClient.Snapshot(8L, "测试车队", "TRUCKING", "ACTIVE", List.of(), "DOMESTIC");
|
||||
when(suppliers.domesticTrucking(8L, null)).thenReturn(supplier);
|
||||
when(suppliers.fee(8L, "TRUCKING")).thenReturn(supplier);
|
||||
var plan = new LoadingPlanEntity(); plan.setId(10L); plan.setContainerBookingId(1L);
|
||||
var container = new ContainerBookingEntity(); container.setId(1L); container.setContainerNo("TEST1234567");
|
||||
|
||||
@@ -58,8 +58,8 @@ class TruckAppointmentServiceTest {
|
||||
return null;
|
||||
}).when(repository).insert(any());
|
||||
lenient().when(documentNumbers.next("TA")).thenReturn("TA-260818-0001");
|
||||
when(suppliers.trucking(any(), any())).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(8L, "Canonical Carrier", "TRUCKING", "ACTIVE", java.util.List.of()));
|
||||
when(suppliers.domesticTrucking(any(), any())).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(8L, "Canonical Carrier", "TRUCKING", "ACTIVE", java.util.List.of(), "DOMESTIC"));
|
||||
lenient().when(repository.attachments(anyLong())).thenReturn(List.of());
|
||||
OceanBookingEntity booking = releasedBooking();
|
||||
lenient().when(oceanBookings.find(99L)).thenReturn(booking);
|
||||
@@ -536,7 +536,7 @@ class TruckAppointmentServiceTest {
|
||||
|
||||
@Test void createRejectsInvalidTruckingSupplierWithoutWriting() {
|
||||
SaveRequest request = validRequest();
|
||||
when(suppliers.trucking(8L, null)).thenThrow(
|
||||
when(suppliers.domesticTrucking(8L, null)).thenThrow(
|
||||
new BizException(com.baiyue.common.core.api.ResultCode.CONFLICT, "拖车服务商未启用"));
|
||||
|
||||
assertThatThrownBy(() -> service.create(7L, "admin", request))
|
||||
|
||||
+25
-5
@@ -28,7 +28,7 @@ class WarehouseSupplierSnapshotServiceTest {
|
||||
|
||||
@Test
|
||||
void rejectsFreeTextWithoutSupplierId() {
|
||||
assertThatThrownBy(() -> service.trucking(null, "任意承运商"))
|
||||
assertThatThrownBy(() -> service.domesticTrucking(null, "任意承运商"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("自由文本");
|
||||
verifyNoInteractions(client);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class WarehouseSupplierSnapshotServiceTest {
|
||||
@Test
|
||||
void resolvesActiveBookingSupplierByCategoryWithoutScopeAndUsesServerName() {
|
||||
when(client.get("internal-token", 7L, true, "BOOKING"))
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(7L, "海运代理", "BOOKING", "ACTIVE", java.util.List.of("MATSON"))));
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(7L, "海运代理", "BOOKING", "ACTIVE", java.util.List.of("MATSON"), null)));
|
||||
var snapshot = service.booking(7L, "海运代理");
|
||||
assertThat(snapshot.name()).isEqualTo("海运代理");
|
||||
verify(client).get("internal-token", 7L, true, "BOOKING");
|
||||
@@ -46,7 +46,7 @@ class WarehouseSupplierSnapshotServiceTest {
|
||||
void feeWithoutCategoryAcceptsAnyActiveWarehouseSupplier() {
|
||||
when(client.get("internal-token", 8L, true, null))
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(
|
||||
8L, "任意启用供应商", "CERTIFICATE", "ACTIVE", java.util.List.of())));
|
||||
8L, "任意启用供应商", "CERTIFICATE", "ACTIVE", java.util.List.of(), null)));
|
||||
|
||||
assertThat(service.fee(8L, null).name()).isEqualTo("任意启用供应商");
|
||||
verify(client).get("internal-token", 8L, true, null);
|
||||
@@ -55,7 +55,7 @@ class WarehouseSupplierSnapshotServiceTest {
|
||||
@Test
|
||||
void rejectsClientNameThatDiffersFromWarehouseSnapshot() {
|
||||
when(client.get(anyString(), eq(9L), eq(true), eq("CUSTOMS")))
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(9L, "真实报关行", "CUSTOMS", "ACTIVE", java.util.List.of())));
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(9L, "真实报关行", "CUSTOMS", "ACTIVE", java.util.List.of(), null)));
|
||||
assertThatThrownBy(() -> service.customs(9L, "伪造名称"))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("不一致");
|
||||
}
|
||||
@@ -64,9 +64,29 @@ class WarehouseSupplierSnapshotServiceTest {
|
||||
void rejectsSupplierSnapshotWithWrongCategoryOrInactiveStatus() {
|
||||
when(client.get("internal-token", 7L, true, "BOOKING"))
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(
|
||||
7L, "错误代理", "TRUCKING", "ACTIVE", java.util.List.of())));
|
||||
7L, "错误代理", "TRUCKING", "ACTIVE", java.util.List.of(), "DOMESTIC")));
|
||||
|
||||
assertThatThrownBy(() -> service.booking(7L, null))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("类别不匹配");
|
||||
}
|
||||
|
||||
@Test void truckingScopesAreMutuallyExclusiveAndMissingScopeIsRejected() {
|
||||
for (String scope : new String[] {"DOMESTIC", "OVERSEAS", null}) {
|
||||
when(client.get("internal-token", 7L, true, "TRUCKING"))
|
||||
.thenReturn(ApiResponse.success(new WarehouseSupplierClient.Snapshot(
|
||||
7L, "车队", "TRUCKING", "ACTIVE", java.util.List.of(), scope)));
|
||||
if ("DOMESTIC".equals(scope)) {
|
||||
assertThat(service.domesticTrucking(7L, null).name()).isEqualTo("车队");
|
||||
} else {
|
||||
assertThatThrownBy(() -> service.domesticTrucking(7L, null))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("国内拖车");
|
||||
}
|
||||
if ("OVERSEAS".equals(scope)) {
|
||||
assertThat(service.overseasTrucking(7L, null).name()).isEqualTo("车队");
|
||||
} else {
|
||||
assertThatThrownBy(() -> service.overseasTrucking(7L, null))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("海外车队");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -72,7 +72,7 @@ class TerminalDrayageServiceTest {
|
||||
new FleetSelectionRequest(0, 91L, null, null)))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessage("货柜实际到达目的港后才能安排码头车队");
|
||||
verify(suppliers, never()).trucking(anyLong(), any());
|
||||
verify(suppliers, never()).overseasTrucking(anyLong(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,8 +82,8 @@ class TerminalDrayageServiceTest {
|
||||
when(mapper.context(11L)).thenReturn(context);
|
||||
when(mapper.lock(11L)).thenReturn(null);
|
||||
when(mapper.operation(11L, "fleet-1")).thenReturn(null);
|
||||
when(suppliers.trucking(91L, "用户提示名")).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(91L, "服务端车队", "TRUCKING", "ACTIVE", List.of()));
|
||||
when(suppliers.overseasTrucking(91L, "用户提示名")).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(91L, "服务端车队", "TRUCKING", "ACTIVE", List.of(), "OVERSEAS"));
|
||||
AtomicReference<TerminalDrayageEntity> stored = new AtomicReference<>();
|
||||
when(mapper.insert(any(TerminalDrayageEntity.class))).thenAnswer(invocation -> {
|
||||
TerminalDrayageEntity value = invocation.getArgument(0);
|
||||
@@ -256,8 +256,8 @@ class TerminalDrayageServiceTest {
|
||||
when(mapper.lockContext(11L)).thenReturn(context);
|
||||
when(mapper.context(11L)).thenReturn(context);
|
||||
when(mapper.lock(11L)).thenReturn(null);
|
||||
when(suppliers.trucking(91L, null)).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(91L, "服务端车队", "TRUCKING", "ACTIVE", List.of()));
|
||||
when(suppliers.overseasTrucking(91L, null)).thenReturn(
|
||||
new WarehouseSupplierClient.Snapshot(91L, "服务端车队", "TRUCKING", "ACTIVE", List.of(), "OVERSEAS"));
|
||||
AtomicReference<TerminalDrayageEntity> stored = new AtomicReference<>();
|
||||
AtomicReference<Operation> operation = new AtomicReference<>();
|
||||
when(mapper.insert(any(TerminalDrayageEntity.class))).thenAnswer(invocation -> {
|
||||
@@ -279,7 +279,7 @@ class TerminalDrayageServiceTest {
|
||||
assertThat(replay).isEqualTo(first);
|
||||
verify(mapper, times(1)).insert(any(TerminalDrayageEntity.class));
|
||||
verify(mapper, times(1)).insertOperation(anyLong(), anyLong(), anyString(), anyString(), anyString(), anyInt(), anyLong());
|
||||
verify(suppliers, times(1)).trucking(91L, null);
|
||||
verify(suppliers, times(1)).overseasTrucking(91L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -317,7 +317,7 @@ class TerminalDrayageServiceTest {
|
||||
void selectingSameFleetDoesNotQueueMailOrChangeVersion() {
|
||||
when(mapper.lockContext(11L)).thenReturn(context("ARRIVED_DESTINATION_PORT", null));
|
||||
when(mapper.lock(11L)).thenReturn(row(3));
|
||||
when(suppliers.trucking(91L, null)).thenReturn(new WarehouseSupplierClient.Snapshot(91L,"车队","TRUCKING","ACTIVE",List.of()));
|
||||
when(suppliers.overseasTrucking(91L, null)).thenReturn(new WarehouseSupplierClient.Snapshot(91L,"车队","TRUCKING","ACTIVE",List.of(), "OVERSEAS"));
|
||||
service.selectFleet(11L,7L,"admin","same-fleet",new FleetSelectionRequest(3,91L,null,null));
|
||||
verifyNoInteractions(mails);
|
||||
verify(mapper,never()).updateAggregate(any(),anyInt(),anyLong(),anyString());
|
||||
@@ -332,7 +332,7 @@ class TerminalDrayageServiceTest {
|
||||
when(mapper.lock(11L)).thenReturn(row);
|
||||
when(mapper.find(11L)).thenReturn(row);
|
||||
when(mapper.updateAggregate(any(),anyInt(),anyLong(),anyString())).thenReturn(1);
|
||||
when(suppliers.trucking(92L,null)).thenReturn(new WarehouseSupplierClient.Snapshot(92L,"新车队","TRUCKING","ACTIVE",List.of()));
|
||||
when(suppliers.overseasTrucking(92L,null)).thenReturn(new WarehouseSupplierClient.Snapshot(92L,"新车队","TRUCKING","ACTIVE",List.of(), "OVERSEAS"));
|
||||
service.selectFleet(11L,7L,"admin","change-fleet",new FleetSelectionRequest(3,92L,null,null));
|
||||
var ordered = org.mockito.Mockito.inOrder(mails,mapper);
|
||||
ordered.verify(mails).replaceFleet(11L,"MSCU1234567",91L,92L,7L);
|
||||
|
||||
Reference in New Issue
Block a user