41 lines
1.9 KiB
TypeScript
41 lines
1.9 KiB
TypeScript
// Round 65 W4: closed-loop APS order/MRP frontend contract guard.
|
|
// Source-level by design: validates backward-compatible typing and no-fake-success UI copy
|
|
// without mutating a live APS world or requiring authentication.
|
|
import { expect, test } from '@playwright/test';
|
|
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
|
|
const webRoot = path.resolve(process.cwd());
|
|
|
|
test('订单面板消费 closedLoop 证据并明确六阶段门禁', async () => {
|
|
const source = await readFile(path.join(webRoot, 'src/orders/OrderPanel.tsx'), 'utf8');
|
|
|
|
expect(source).toContain('setClosedLoop(res.result?.closedLoop ?? null)');
|
|
for (const label of ['商务订单', 'BOM/供需净算', '制造需求准入', '排产草案', 'P2 发布', 'P3 MES']) {
|
|
expect(source).toContain(label);
|
|
}
|
|
expect(source).toContain('它们仍是制造需求,不是已释放生产订单');
|
|
expect(source).toContain('不会自动转采购');
|
|
expect(source).toContain('待独立确认');
|
|
expect(source).toContain('closed-loop-manufacturing-demands');
|
|
expect(source).toContain('closed-loop-blockers');
|
|
});
|
|
|
|
test('MRP 分解类型保持旧清单并可选扩展 closedLoop 契约', async () => {
|
|
const source = await readFile(path.join(webRoot, 'src/api/types.ts'), 'utf8');
|
|
|
|
expect(source).toContain('make: MakeSuggestion[];');
|
|
expect(source).toContain('purchase: PurchaseSuggestion[];');
|
|
expect(source).toContain('outsource: OutsourceSuggestion[];');
|
|
expect(source).toContain('closedLoop?: MrpClosedLoopDecomposition;');
|
|
for (const field of [
|
|
'problemId: string;', 'sourceHash: string;', 'businessDate: string;',
|
|
'summary: ClosedLoopSummary;', 'projection: ClosedLoopProjection;',
|
|
'manufacturingDemands: ClosedLoopManufacturingDemand[];',
|
|
'supplyEvents: ClosedLoopSupplyEvent[];', 'blockers: ClosedLoopBlocker[];',
|
|
'schedulingProblemV2: SchedulingProblemV2Projection;',
|
|
]) {
|
|
expect(source).toContain(field);
|
|
}
|
|
});
|