fix(number-fields): избегаем потери точности длинных чисел
- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
This commit is contained in:
72
server/utils/validate-immutable-fields.ts
Normal file
72
server/utils/validate-immutable-fields.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Проверка условной неизменности полей формы.
|
||||
*/
|
||||
|
||||
import { isFieldImmutable } from "@shared/field-conditions";
|
||||
import { buildFieldConditionContext } from "./field-condition-context";
|
||||
|
||||
export interface ValidateImmutableFieldsOptions {
|
||||
task: { currentStatusId?: number | null; formId?: number; [key: string]: any };
|
||||
formFields: Array<{
|
||||
id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
type?: string;
|
||||
options?: unknown;
|
||||
immutableRules?: any;
|
||||
autoProlongationLabel?: string | null;
|
||||
}>;
|
||||
changedFieldIds: number[];
|
||||
existingFieldValues?: Array<{ fieldId: number; value: unknown }>;
|
||||
organizationId: number;
|
||||
storage: any;
|
||||
isCreation?: boolean;
|
||||
statuses?: Array<{ id: number; position: number; isFinal?: boolean | null }>;
|
||||
users?: Array<{ id: number; firstName?: string | null; middleName?: string | null; lastName?: string | null; email?: string }>;
|
||||
roles?: Array<{ id: number; name?: string }>;
|
||||
}
|
||||
|
||||
export async function validateImmutableFields(
|
||||
options: ValidateImmutableFieldsOptions
|
||||
): Promise<string[]> {
|
||||
const {
|
||||
task,
|
||||
formFields,
|
||||
changedFieldIds,
|
||||
existingFieldValues,
|
||||
organizationId,
|
||||
storage,
|
||||
statuses: providedStatuses,
|
||||
users: providedUsers,
|
||||
roles: providedRoles,
|
||||
} = options;
|
||||
|
||||
const fieldsWithRules = formFields.filter(
|
||||
(f) => f.immutableRules && f.immutableRules.enabled && changedFieldIds.includes(f.id)
|
||||
);
|
||||
if (fieldsWithRules.length === 0) return [];
|
||||
|
||||
const ctxResult = await buildFieldConditionContext({
|
||||
task,
|
||||
formFields,
|
||||
organizationId,
|
||||
storage,
|
||||
isCreation: options.isCreation,
|
||||
statuses: providedStatuses,
|
||||
existingFieldValues,
|
||||
users: providedUsers,
|
||||
roles: providedRoles,
|
||||
});
|
||||
|
||||
const { fields, fieldValues, ...context } = ctxResult;
|
||||
|
||||
const errors: string[] = [];
|
||||
for (const field of fieldsWithRules) {
|
||||
const immutable = isFieldImmutable(field as any, task, fieldValues, fields, context);
|
||||
if (immutable) {
|
||||
errors.push(`Поле «${field.name}» не может быть изменено в текущем состоянии`);
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
Reference in New Issue
Block a user