This commit is contained in:
2026-08-15 09:49:09 +08:00
parent 2bf3ff9d8e
commit c07af65c3b
3 changed files with 45 additions and 7 deletions
@@ -2,15 +2,52 @@ const MODULE = 'phase3-evidence-gate'
const OPTIONS = { scenario: 'loading-evidence-gate', deploymentBlocker: true }
function id(value) { return value == null ? '' : String(value) }
function successful(response) { return response?.http === 200 && String(response?.body?.code ?? '') === '200' }
export async function run(context) {
const fixture = context.createdResources?.phase3Loading
if (!fixture?.tenantId || !fixture?.inboundId || fixture.marker !== context.marker) {
const tenantId = id(fixture?.tenantId)
const inboundId = id(fixture?.inboundId)
const taskId = id(fixture?.canonicalPdaTaskId || fixture?.pickingTaskId)
const loadingPlanId = id(fixture?.loadingPlanId)
const containerBookingId = id(fixture?.containerBookingId)
const warehouseId = id(fixture?.warehouseId)
if (!tenantId || !inboundId || !taskId || !loadingPlanId || !containerBookingId || !warehouseId
|| fixture.marker !== context.marker) {
context.addCoverageGap(MODULE, OPTIONS.scenario, '五类证据多图追加、作废审计和有效证据门禁',
'本轮未取得 phase3-loading 的 marker 隔离证据 fixture,未使用历史资源', 'fixture')
'本轮未取得带 taskId/inboundId/loadingPlanId/containerBookingId 的 phase3-loading marker 隔离证据 fixture,未使用历史资源', 'fixture')
return
}
const path = `/api/platform/v1/inbounds/${fixture.inboundId}/loading/evidence?tenantId=${encodeURIComponent(fixture.tenantId)}`
// AWAITING_REVIEW is a PDA workflow state, not evidence permission. Evidence is
// opened only after the server-side inbound aggregate has entered LOADING.
const taskResponse = await context.request('GET',
`/api/platform/v1/first-leg/pda-loading/tasks?loadingPlanId=${encodeURIComponent(loadingPlanId)}&warehouseId=${encodeURIComponent(warehouseId)}`)
const task = successful(taskResponse) ? taskResponse.body?.data : null
const taskItem = task?.items?.find?.((item) => id(item?.inboundId) === inboundId)
const taskIdentityValid = id(task?.id) === taskId
&& id(task?.loadingPlanId) === loadingPlanId
&& id(task?.containerBookingId) === containerBookingId
&& Boolean(taskItem) && id(taskItem?.inboundId) === inboundId
context.assert(MODULE, '证据前置任务身份使用本轮四元稳定关联', taskResponse,
taskIdentityValid,
`taskId=${id(task?.id) || 'missing'}, inboundId=${id(taskItem?.inboundId) || 'missing'}, loadingPlanId=${id(task?.loadingPlanId) || 'missing'}, containerBookingId=${id(task?.containerBookingId) || 'missing'}`, OPTIONS)
if (!taskIdentityValid) return
const inboundResponse = await context.request('GET',
`/api/platform/inbounds/${encodeURIComponent(inboundId)}?tenantId=${encodeURIComponent(tenantId)}`)
const inbound = successful(inboundResponse) ? inboundResponse.body?.data : null
const serverLoading = inbound?.summary?.processStatus === 'LOADING'
context.assert(MODULE, '服务端入库进入 LOADING 后才开放装柜证据', inboundResponse,
serverLoading,
`processStatus=${inbound?.summary?.processStatus || 'missing'}, taskWorkflow=${task?.workflowStatus || 'missing'}`, OPTIONS)
if (!serverLoading) {
context.addCoverageGap(MODULE, OPTIONS.scenario, '服务端装柜阶段前不请求证据',
`taskId=${taskId}, inboundId=${inboundId}, loadingPlanId=${loadingPlanId}, containerBookingId=${containerBookingId}, processStatus=${inbound?.summary?.processStatus || 'missing'};AWAITING_REVIEW 不作为证据开放条件`, 'deployment-blocker')
return
}
const path = `/api/platform/v1/inbounds/${inboundId}/loading/evidence?tenantId=${encodeURIComponent(tenantId)}`
const response = await context.request('GET', path)
const data = context.apiSuccess(MODULE, '复核本轮装柜证据聚合', response, `inboundId=${fixture.inboundId}`, OPTIONS)
const evidences = Array.isArray(data?.evidences) ? data.evidences : []
@@ -8,6 +8,7 @@ import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.warehouse.dto.SupplierDtos.*;
import com.baiyue.warehouse.entity.SupplierEntity;
import com.baiyue.warehouse.service.SupplierService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@@ -33,7 +34,7 @@ public class PlatformSupplierController {
@GetMapping("/{id}") @PreAuthorize("hasAuthority('platform:supplier:list')")
public ApiResponse<SupplierEntity> detail(@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @Min(0) long tenantId, @PathVariable long id) { requirePlatform(user); requireScope(tenantId); return ApiResponse.success(service.detail(id)); }
@PostMapping @PreAuthorize("hasAuthority('platform:supplier:create')")
public ApiResponse<Long> create(@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @Min(0) long tenantId, @Valid @RequestBody SaveRequest request) { requirePlatform(user); requireScope(tenantId); return ApiResponse.success(service.create(request)); }
public ApiResponse<Long> create(@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @Min(0) long tenantId, @Valid @RequestBody SaveRequest request) { requirePlatform(user); requireScope(tenantId); long id = IdWorker.getId(); return ApiResponse.success(service.create(id, request)); }
@PutMapping("/{id}") @PreAuthorize("hasAuthority('platform:supplier:edit')")
public ApiResponse<Void> update(@AuthenticationPrincipal AuthenticatedUser user, @RequestParam @Min(0) long tenantId, @PathVariable long id, @Valid @RequestBody SaveRequest request) { requirePlatform(user); requireScope(tenantId); service.update(id, request); return ApiResponse.success(null); }
@PatchMapping("/{id}/status") @PreAuthorize("hasAuthority('platform:supplier:status')")
@@ -26,11 +26,11 @@ public class SupplierService {
public Stats stats() { return new Stats(repository.count(0, "BOOKING"), repository.count(0, "CUSTOMS"), repository.count(0, "TRUCKING"), repository.count(0, "CERTIFICATE")); }
@Transactional
@BusinessAudit(event = "SUPPLIER_CREATE", resourceType = "SUPPLIER", resourceId = "#request.name", description = "新增供应商", captureBefore = false)
public Long create(SaveRequest request) {
@BusinessAudit(event = "SUPPLIER_CREATE", resourceType = "SUPPLIER", resourceId = "#id", description = "新增供应商", captureBefore = false)
public Long create(long id, SaveRequest request) {
validateScope(request);
ensureName(request.name(), null);
SupplierEntity entity = new SupplierEntity(); entity.setTenantId(0L); copy(entity, request);
SupplierEntity entity = new SupplierEntity(); entity.setId(id); entity.setTenantId(0L); copy(entity, request);
try { repository.insert(entity); } catch (DataIntegrityViolationException e) { throw new BizException(ResultCode.CONFLICT, "供应商名称已存在"); }
return entity.getId();
}