feat(import): harden workbook parser boundaries
This commit is contained in:
@@ -166,6 +166,25 @@ function getSlotHalfDayPart(slotLabel: string | null): "AFTERNOON" | "MORNING" |
|
||||
return null;
|
||||
}
|
||||
|
||||
function isPlanningSummaryRow(row: ReadonlyArray<WorksheetCellValue>): boolean {
|
||||
if ((row[0] ?? null) !== null || (row[1] ?? null) !== null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const repeatedLabels = row
|
||||
.slice(DISPO_EID_COLUMN - 1, 9)
|
||||
.map((value) => normalizeNullableWorkbookValue(value))
|
||||
.filter((value): value is string => value !== null);
|
||||
if (repeatedLabels.length === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalizedLabels = new Set(repeatedLabels.map((value) => value.toLowerCase()));
|
||||
const label = repeatedLabels[0] ?? null;
|
||||
|
||||
return normalizedLabels.size === 1 && label !== null && label.startsWith("(") && label.endsWith(")");
|
||||
}
|
||||
|
||||
function buildPlanningColumns(rows: ReadonlyArray<ReadonlyArray<WorksheetCellValue>>) {
|
||||
const columns: PlanningColumn[] = [];
|
||||
const headerWidth = Math.max(rows[DISPO_DATE_ROW - 1]?.length ?? 0, rows[DISPO_SLOT_ROW - 1]?.length ?? 0);
|
||||
@@ -483,6 +502,9 @@ export async function parseDispoPlanningWorkbook(
|
||||
|
||||
for (let rowNumber = DISPO_DATA_START_ROW; rowNumber <= rows.length; rowNumber += 1) {
|
||||
const row = rows[rowNumber - 1] ?? [];
|
||||
if (isPlanningSummaryRow(row)) {
|
||||
continue;
|
||||
}
|
||||
const eid = normalizeNullableWorkbookValue(row[DISPO_EID_COLUMN - 1]);
|
||||
|
||||
if (!eid) {
|
||||
|
||||
Reference in New Issue
Block a user