fix(parse): reject split pier tables and block sheets that fail to build
- E05: a sheet whose pier, IP, or bearing table is not on the same sheet is not selectable (spec 2.2: one sheet per pier) - a sheet is selectable only if every pier in it builds; the reason is shown next to the sheet instead of a selectable sheet with an unchecked pier Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
69922cfa35
commit
4f21bd63bf
3 files changed
+36
No files matched your search
@@ -78,9 +78,28 @@ function parseSheet(grid: Grid, sheet: string, issues: Issue[]): PierInput[] {
|
||||
}
|
||||
|
||||
const piers: PierInput[] = [];
|
||||
if (pierHeaders.length === 0 && (ipHeaders.length > 0 || bearingHeaders.length > 0)) {
|
||||
issues.push({
|
||||
code: 'E05',
|
||||
level: 'E',
|
||||
message: `${sheet}: 교각 정보 표가 이 시트에 없습니다. 교각 1기의 세 표(교각 정보·IP·받침)를 한 시트에 두세요 (시트 1장 = 교각 1기).`,
|
||||
});
|
||||
}
|
||||
for (const h of pierHeaders) {
|
||||
for (const { cells, index } of readBlock(grid, h)) {
|
||||
const name = String(cells[0]);
|
||||
const pierIps = ips.filter((p) => p.pier === name);
|
||||
const pierBearings = bearings.filter((b) => b.pier === name);
|
||||
if (pierIps.length === 0 || pierBearings.length === 0) {
|
||||
const missing = [pierIps.length === 0 ? 'IP' : null, pierBearings.length === 0 ? '받침' : null].filter(Boolean).join('·');
|
||||
issues.push({
|
||||
code: 'E05',
|
||||
level: 'E',
|
||||
pier: name,
|
||||
message: `${index + 1}행: ${missing} 표가 이 시트에 없습니다. 교각 1기의 세 표를 한 시트에 두세요 (시트 1장 = 교각 1기).`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const bad = bearings.find((b) => b.pier === name && !b.azimuthOk);
|
||||
if (bad) {
|
||||
issues.push({
|
||||
|
||||
@@ -454,6 +454,12 @@ function updateApply(): void {
|
||||
function loadBytes(bytes: Uint8Array, fileName: string): void {
|
||||
const { piers, sheets } = parseWorkbook(XLSX.read(bytes, { type: 'array' }));
|
||||
const entries = piers.map((input) => buildEntry(input, false));
|
||||
// A sheet is selectable only if every pier in it builds. Show the reason next to the sheet.
|
||||
for (const sheet of sheets) {
|
||||
const own = entries.filter((e) => e.input.sheet === sheet.name);
|
||||
for (const e of own) sheet.issues.push(...e.issues.filter((i) => i.level === 'E'));
|
||||
sheet.ok = sheet.ok && own.every((e) => e.model !== null);
|
||||
}
|
||||
const pending: Pending = { fileName, entries, sheets, preview: null };
|
||||
for (const e of entries) e.checked = selectable(pending, e);
|
||||
pending.preview = entries.find((e) => selectable(pending, e))?.input.name ?? entries[0]?.input.name ?? null;
|
||||
|
||||
@@ -49,3 +49,14 @@ describe('sheet report (spec §2.3)', () => {
|
||||
expect(piers).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('tables split across sheets (spec §2.2: 시트 1장 = 교각 1기)', () => {
|
||||
it('reports E05 and drops the pier when the IP table is not on the same sheet', () => {
|
||||
const wb = loadWorkbook();
|
||||
wb.Sheets['intent.PR']['B25'].v = '기타';
|
||||
const { piers, sheets, issues } = parseWorkbook(wb);
|
||||
expect(issues.map((i) => i.code)).toContain('E05');
|
||||
expect(piers).toHaveLength(0);
|
||||
expect(sheets[0].ok).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user