209 lines
7.7 KiB
JavaScript
209 lines
7.7 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const root = path.resolve(__dirname, '..');
|
|
|
|
function read(relativePath) {
|
|
return fs.readFileSync(path.join(root, relativePath), 'utf8');
|
|
}
|
|
|
|
function assertContains(file, needle, message) {
|
|
const content = read(file);
|
|
if (!content.includes(needle)) {
|
|
throw new Error(`${message}\nMissing in ${file}: ${needle}`);
|
|
}
|
|
}
|
|
|
|
function assertMatches(file, pattern, message) {
|
|
const content = read(file);
|
|
if (!pattern.test(content)) {
|
|
throw new Error(`${message}\nPattern not found in ${file}: ${pattern}`);
|
|
}
|
|
}
|
|
|
|
assertMatches(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/bas/stock/service/impl/BasStockServiceImpl.java',
|
|
/"KC"\s*\+\s*STOCK_ID_FORMATTER\.format/,
|
|
'Manual stock creation must generate KC + millisecond timestamp IDs.'
|
|
);
|
|
|
|
assertContains(
|
|
'sql/bas_stock_master_detail.sql',
|
|
"in_type",
|
|
'Inbound completion stock generation must persist the real inbound type.'
|
|
);
|
|
assertMatches(
|
|
'sql/bas_stock_master_detail.sql',
|
|
/'KC'\s*\+\s*FORMAT\(@now,\s*'yyyyMMddHHmmssfff'\)/,
|
|
'Inbound completion procedure must generate KC + millisecond timestamp stock IDs.'
|
|
);
|
|
assertContains(
|
|
'sql/bas_stock_master_detail.sql',
|
|
"@stock_id + N'-' + CONVERT",
|
|
'Inbound completion stock detail IDs must use stock ID plus detail sequence.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/resources/mapper/bas/BasStockDetailMapper.xml',
|
|
'bsd.product_id, bsd.product_name',
|
|
'Stock detail queries must keep material code and material name in separate columns.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/bas/stock/index.vue',
|
|
'label="物料编码" align="center" prop="productId"',
|
|
'Stock detail UI must render material code from productId.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/bas/stock/index.vue',
|
|
'label="物料名称" align="center" prop="productName"',
|
|
'Stock detail UI must render material name from productName.'
|
|
);
|
|
|
|
const outJob = read('ruoyi-ui/src/views/out/job/index.vue');
|
|
if (!outJob.includes('prop="status"') || !outJob.includes('dict.type.mydo_job_status')) {
|
|
throw new Error('Outbound job page must filter/render task status with mydo_job_status.');
|
|
}
|
|
if (!outJob.includes('dict.type.out_job_type') || !outJob.includes("dicts: ['mydo_job_execution_phase', 'mydo_job_status', 'out_job_type']")) {
|
|
throw new Error('Outbound job page must render task type with out_job_type.');
|
|
}
|
|
if (!outJob.includes("parseTime(scope.row.createTime")) {
|
|
throw new Error('Outbound job page must render createTime from createTime, not createDate.');
|
|
}
|
|
if (!outJob.includes('this.detailQueryParams.status = row.status')) {
|
|
throw new Error('Finished outbound jobs must pass parent status when loading child job details.');
|
|
}
|
|
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/stockout/index.vue',
|
|
'selectedExitId',
|
|
'Outbound allocation UI must require an exit selection.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/stockout/index.vue',
|
|
'listStationPoint',
|
|
'Outbound allocation UI must load warehouse exit/entry-exit station points.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/stockout/index.vue',
|
|
'this.detailQueryParams.status = row.status',
|
|
'Finished outbound bills must pass the parent status when loading child details.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/out/stockout/domain/OutStockoutManualAssignDTO.java',
|
|
'private String exitId;',
|
|
'Manual outbound allocation DTO must carry the selected exit.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/resources/mapper/out/OutStockoutMapper.xml',
|
|
'#{v_exit_id,mode=IN,jdbcType=VARCHAR}',
|
|
'Outbound allocation mapper must pass the selected exit to procedures.'
|
|
);
|
|
assertContains(
|
|
'sql/out_stockout_flow.sql',
|
|
'@v_exit_id varchar(80)',
|
|
'Outbound allocation procedures must accept a selected exit.'
|
|
);
|
|
assertContains(
|
|
'sql/out_stockout_flow.sql',
|
|
'@exit_id = @v_exit_id',
|
|
'Outbound allocation procedure must store the selected exit on generated jobs.'
|
|
);
|
|
|
|
assertContains(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/in/job/service/impl/MydoJobServiceImpl.java',
|
|
'requestWcsCancelBeforeManualCancel',
|
|
'Manual job cancellation must reserve a WCS cancellation check.'
|
|
);
|
|
|
|
assertContains(
|
|
'pda/pages/warehouse/outbound/confirm.vue',
|
|
'扫描托盘条码',
|
|
'PDA outbound confirmation must scan tray barcodes.'
|
|
);
|
|
assertContains(
|
|
'pda/pages/warehouse/outbound/confirm.vue',
|
|
'materials',
|
|
'PDA outbound confirmation must render tray material details.'
|
|
);
|
|
assertContains(
|
|
'pda/pages/warehouse/outbound/confirm.vue',
|
|
'v-model="item.actualQuantity"',
|
|
'PDA outbound confirmation must capture actual outbound quantity per material.'
|
|
);
|
|
assertContains(
|
|
'pda/pages/warehouse/outbound/confirm.vue',
|
|
'materials: this.outboundInfo.materials.map',
|
|
'PDA outbound confirmation must submit actual quantities per material.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java',
|
|
'createReturnInboundJobIfNeeded',
|
|
'PDA outbound confirmation must create return inbound jobs for residual tray materials.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java',
|
|
'jobIdService.getId("HL")',
|
|
'Residual tray return jobs must use the 回流作业 job-id prefix.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/java/com/ruoyi/pda/service/impl/PdaServiceImpl.java',
|
|
'taskNoService.getTaskNo("5")',
|
|
'Residual tray return jobs must use the 回流入库 task-number type.'
|
|
);
|
|
assertContains(
|
|
'sql/20260624_update_job_dicts.sql',
|
|
"N'回流入库'",
|
|
'Inbound job dictionaries must render 回流入库 return jobs.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-admin/src/main/resources/mapper/pda/PdaMapper.xml',
|
|
'selectResidualTrayMaterials',
|
|
'PDA mapper must query residual tray materials after outbound confirmation.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'active-text="所有货位"',
|
|
'Specified-location outbound filter switch must be labelled 所有货位.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'listWarehouse',
|
|
'Specified-location outbound page must load warehouse dropdown options.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'v-model="queryParams.warehouseId"',
|
|
'Specified-location outbound page must filter by warehouse id dropdown.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'@selection-change="handleSelectionChange"',
|
|
'Specified-location outbound table must support selecting locations.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'批量生成作业',
|
|
'Specified-location outbound page must provide a batch generation action.'
|
|
);
|
|
assertContains(
|
|
'ruoyi-ui/src/views/out/locationOutbound/index.vue',
|
|
'Promise.all(rows.map',
|
|
'Specified-location outbound page must generate outbound jobs for selected locations.'
|
|
);
|
|
const locationOutbound = read('ruoyi-ui/src/views/out/locationOutbound/index.vue');
|
|
if (locationOutbound.includes('type="expand"')) {
|
|
throw new Error('Specified-location outbound page must use a lower child-detail table instead of expand rows.');
|
|
}
|
|
if (!locationOutbound.includes('@row-click="handleRowClick"') ||
|
|
!locationOutbound.includes('currentLocation') ||
|
|
!locationOutbound.includes('locationDetailList')) {
|
|
throw new Error('Specified-location outbound page must click a parent location row and show child details below.');
|
|
}
|
|
if (!locationOutbound.includes('cargoSpaceId: row.cargoSpaceId')) {
|
|
throw new Error('Specified-location outbound generation must send cargoSpaceId so empty locations can generate jobs.');
|
|
}
|
|
if (!locationOutbound.includes("['1', '6'].includes(String(row.cargoSpaceStatus))")) {
|
|
throw new Error('Specified-location outbound must allow empty and no-stock abnormal locations to generate jobs.');
|
|
}
|
|
|
|
console.log('Outbound and stock regression checks passed.');
|