fix: числовая сортировка date/datetime/number полей в реестре задач

Сортировка кастомных полей шла лексикографически по отображаемой строке:
даты «ДД.ММ.ГГГГ» сортировались по дню («01.12.2025» < «02.01.2024»),
числа как строки («10» < «9»). Теперь для field_<id> типов date/datetime/number
сравнение идёт по сырому значению (timestamp/число), пустые — всегда в конец.
This commit is contained in:
2026-07-24 12:03:16 +03:00
parent 59079992dc
commit c152a670ae

View File

@@ -267,6 +267,30 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
const DATE_COLS = new Set(['createdAt', 'updatedAt', 'dueDate', 'completedAt']);
// Числовые и датовые кастомные поля сортируем по сырому значению,
// а не по отображаемой строке (иначе «01.12.2025» < «02.01.2024» и «10» < «9»)
type TaskWithFV = Task & { fieldValues?: Record<number, unknown> };
let numericFieldId: number | null = null;
let numericFieldIsDate = false;
if (sortColumn.startsWith('field_')) {
const fieldId = parseInt(sortColumn.replace('field_', ''));
const field = formFields.find((f) => f.id === fieldId);
if (field && ['date', 'datetime', 'number'].includes(field.type)) {
numericFieldId = fieldId;
numericFieldIsDate = field.type === 'date' || field.type === 'datetime';
}
}
const toSortNumber = (t: TaskWithFV): number | null => {
const v = t.fieldValues?.[numericFieldId!];
if (v === undefined || v === null || v === '') return null;
if (numericFieldIsDate) {
const ts = new Date(String(v)).getTime();
return isNaN(ts) ? null : ts;
}
const n = Number(String(v).replace(/\s/g, ''));
return isNaN(n) ? null : n;
};
tasks = [...tasks].sort((a, b) => {
if (DATE_COLS.has(sortColumn)) {
const _a = (a as Record<string, unknown>)[sortColumn];
@@ -275,6 +299,15 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
const bv = _b ? new Date(String(_b)).getTime() : 0;
return sortDir === 'asc' ? av - bv : bv - av;
}
if (numericFieldId !== null) {
const av = toSortNumber(a as TaskWithFV);
const bv = toSortNumber(b as TaskWithFV);
// Пустые значения всегда в конец независимо от направления
if (av === null && bv === null) return 0;
if (av === null) return 1;
if (bv === null) return -1;
return sortDir === 'asc' ? av - bv : bv - av;
}
const av = getTaskColumnValue(a, sortColumn, statusMap, userMap, formFields, roleMap, undefined, legalEntityMap, taskTitleMap).toLowerCase();
const bv = getTaskColumnValue(b, sortColumn, statusMap, userMap, formFields, roleMap, undefined, legalEntityMap, taskTitleMap).toLowerCase();
const cmp = av.localeCompare(bv, 'ru');