Примеры скриптов
Ниже собраны примеры готовых скриптов по категориям: заполнение полей, валидация и фильтрация значений. Их можно использовать в различных формах, достаточно скорректировать названия полей. Вы можете комбинировать и расширять примеры, усложняя логику для конкретных бизнес-задач.
Заполнение полей
Скопировать значение одного поля в другое
Копируем значение из поля Поле-источник в поле Поле-приемник (типы полей должны совпадать).
form.onChange(['Поле-источник'], true)
.setValue('Поле-приемник', state => {
const [value] = state.changes;
return value;
});
Вычислить сумму (разницу, процент) нескольких полей
В этом примере скрипт прибавляет премию сотрудника к его окладу и рассчитывает НДФЛ от полученной суммы. Затем вычитает НДФЛ из этой суммы и выводит итоговую выплату за месяц.
form.onChange(['Оклад', 'Премия'])
.setValues(['НДФЛ (13%)', 'Итого к выплате за месяц'], state => {
const [salary, bonus] = state.changes;
if (!salary || !bonus)
return null;
const ndflTax = (salary.value + bonus.value) * 0.13;
const result = (salary.value + bonus.value) - ndflTax;
return [ndflTax, result];
});

Вывести значение колонки справочника
Здесь Справочник — название поля с вашим справочником, Колонка — название колонки справочника, а Текст — поле типа Текст, в котором будет сохранено значение.
form.onChange(['Справочник'])
.setValue('Текст', state => {
const [item] = state.changes;
return item?.columns['Колонка'];
});
Перенос крайнего срока в зависимости от приоритета
С возможностью установки произвольного срока.
form.onChange(['Высокий приоритет', 'Перенос даты'])
.setValue('Срок', state => {
const [checkmark, customDue] = state.changes;
if (customDue?.date)
return {date: customDue.date};
if (checkmark?.checked)
return {days_from_create: 1};
return {days_from_create: 3};
});
Установка срока за N дней до указанной даты
В этом примере срок устанавливается автоматически — за семь дней до даты, указанной при заполнении.
form.onChange(['Дата'])
.setValues(['Срок'], state => {
const [dateValue] = state.changes;
if (!dateValue)
return null;
const dueDate = new Date(dateValue.date + 'T10:00:00Z');
const daysBeforeDate = 7;
dueDate.setDate(dueDate.getDate() - daysBeforeDate);
return [{date: dueDate.toDateString()}];
});
Назначение ответственного в задаче
Скрипт устанавливает ответственного в задаче в зависимости от значения поля типа Число.
form.onChange(['Сумма контракта'])
.setAssignee(state => {
const [summaKontrakta] = state.changes;
if (summaKontrakta.value > 50000)
// ID пользователя, отвечающего за крупные контракты
return 321;
// ID пользователя, отвечающего за обычные контракты
return 123;
});
Подсчёт рабочих дней между датами
Скрипт на основе производственного календаря РФ считает количество рабочих дней между указанными датами (поля start_date и end_date) и записывает результат в числовое поле days.
form.onChange(['start_date', 'end_date']).setValue('days', state => {
const [start_date, end_date] = state.changes;
return form.getDaysCount(start_date.date, end_date.date, {
exclude: 'nonWorking',
calendar: 'ru'
});
});
Подсчёт суммы в строках таблицы и скидки
Скрипт считает сумму значений в заполненной таблице и применяет указанную скидку.
form.onChange(["product", "quantity", "discount"])
.setValues(["price_for_one", "total_price"], state => {
const [product, quantity, discount] = state.changes;
if (!product?.columns) return [null, null];
const discount_rate = discount?.value
? discount.value / 100
: 0;
const item_price = product.columns["Цена"]
? Number(product.columns["Цена"]) * (1 - discount_rate)
: 0;
return quantity?.value ? [item_price, item_price * quantity.value] : [item_price, 0];
});
Выбор значения из справочника по полю с типом Контакт
Иногда нужно подставлять в заявку ФИО сотрудника в родительном падеже. Простой пример — заявление на отпуск. Чтобы Pyrus делал это автоматически, создаём справочник со списком сотрудников, в котором есть колонка с их ФИО в родительном падеже. Далее подключаем к форме такой скрипт:
const catalogPromise = form.getCatalog(ID_справочника);
form.onChange(['Отпускник'])
.setValueAsync('От (ФИО):', async state => {
const [contactField] = state.changes;
const catalogItems = await catalogPromise;
if (!catalogItems || !contactField || !contactField.person_id)
return null;
const filteredRow = catalogItems
.find(item => item.columns['Сотрудник'] == `${contactField.first_name} ${contactField.last_name}`);
return filteredRow ? filteredRow.columns['ФИО Род'] : null;
});
В этом примере:
- Отпускник — название поля типа Контакт;
- Сотрудник и ФИО Род — названия колонок справочника, в котором мы ищем значение по выбранному полю;
- От (ФИО): — поле типа Текст, в котором сохраняется найденное значение из справочника.
Автоматическое заполнение срока SLA
Укажите в скрипте своё время решения и названия полей. Вместо числовых констант можно использовать переменные или формулы для расчёта времени решения. Когда в заявке меняются значения полей Приоритет и Клиент, скрипт срабатывает и устанавливает один из указанных в нём сроков.
form.onChange(['Приоритет', 'Клиент'])
.setValue('Срок', state => {
const [priority, client] = state.changes;
if (!priority || !priority.columns || !client || !client.columns)
return null;
const tariff = client.columns['Тариф'];
const priorityValue = priority.columns['Приоритет'];
const hours = getSlaHoursByTariffAndPriority(tariff, priorityValue);
if (hours === undefined)
return null;
return {hours_from_create: hours};
});
function getSlaHoursByTariffAndPriority(tariff, priority) {
switch (tariff) {
case 'Базовый':
switch (priority) {
case 'Низкий' : return 64;
case 'Средний': return 32;
case 'Высокий': return 16;
}
case 'Стандарт':
switch (priority) {
case 'Низкий' : return 32;
case 'Средний': return 16;
case 'Высокий': return 8;
}
case 'Премиум':
switch (priority) {
case 'Низкий' : return 16;
case 'Средний': return 8;
case 'Высокий': return 4;
}
default:
return undefined;
}
}
Валидация
Проверка, что дата окончания не раньше даты начала
Скрипт следит за полями Дата начала и Дата окончания (например, отпуска или командировки). Если обе даты заполнены и дата окончания оказывается раньше даты начала, скрипт показывает ошибку и не даёт сохранить форму.
form.onChange(['Дата начала', 'Дата окончания'])
.validate('Дата окончания', state => {
const [start, end] = state.changes;
if (!start || !end)
return null;
if (start.date && end.date && start.date >= end.date)
return {
errorMessage: 'Не может быть раньше даты начала'
};
return null;
});
Проверка, что заполнено хотя бы одно поле
Скрипт следит за полями Эл. почта и Телефон. Если оба поля пустые, он показывает ошибку и не даёт сохранить форму. Достаточно заполнить хотя бы одно из полей.
form.onChange(['Эл. почта', 'Телефон'], true)
.validate('Эл. почта', state => {
const [email, phone] = state.changes;
const emailIsEmpty = !email || !email.text;
const phoneIsEmpty = !phone || !phone.text;
if (emailIsEmpty && phoneIsEmpty)
return {
errorMessage: 'Заполните электронную почту или телефон'
};
return null;
});
Проверяем правильность заполнения текстового поля
Скрипт проверяет, чтобы текстовое поле было заполнено только заглавными латинскими буквами.
form.onChange(["fio_text"], true)
.validate("fio_text", state => {
const [text] = state.changes;
if (!text?.text) return null;
const reg = new RegExp(/^[A-Z'\s]+$/);
if (!reg.test(text.text))
return {
errorMessage: "Обнаружены недопустимые символы"
};
});
Запрет удаления строк в таблице
Скрипт не даёт удалить сохранённые строки из таблицы в форме.
let exist_table = null;
form.onChange(["no_delete_table"], true)
.validate("no_delete_table", state => {
const [table] = state.changes;
if (state.currentStep == 0) return null;
if (!exist_table) {
exist_table = [];
if (table?.value) {
for (let i in table.value) {
exist_table.push(table.value[i].Id);
}
}
return null;
}
if (exist_table.length == 0) return null;
if (!table?.value || table.value.length == 0)
return {
errorMessage: "Нельзя удалять строки таблицы. Перезагрузите страницу"
};
for (let i in exist_table) {
if (!table.value.find(x => x.Id == exist_table[i]))
return {
errorMessage: "Нельзя удалять строки таблицы. Перезагрузите страницу"
};
}
return null;
});
Проверка типа загружаемых файлов
Скрипт позволяет добавить в поле исключительно PDF-файлы.
form.onChange(["files"])
.validate("files", state => {
const [files] = state.changes;
const correct_extensions = ["pdf"];
if (!files?.files) return null;
for (let i in files.files) {
let extension = files.files[i].name.split(".").slice(-1);
if (correct_extensions.indexOf(extension[0]) < 0)
return {
errorMessage: "Можно приложить только pdf"
};
}
return null;
});
Проверка, сколько дней отпуска осталось
Скрипт рассчитывает, сколько у сотрудника осталось дней оплачиваемого отпуска. Данные для расчёта берутся из реестра формы.
form.onChange(["vacation_start", "vacation_end", "employee", "vacation_type"])
.validateAsync("vacation_type", async state => {
const [start, end, employee, vacation_type] = state.changes;
if (!start?.date || !end?.date || !employee?.person_id || !vacation_type?.choice_name)
return null;
if (vacation_type.choice_name != "Оплачиваемый") return null;
const max = 28;
let this_time = daysBetween(new Date(start.date), new Date(end.date)) + 1;
if (this_time > max)
return {
errorMessage: `Выбран промежуток в ${this_time} дней. Максимально ${max}`
};
let today = new Date();
let already_taken = await form.fetchRegister(1027552, f => f
.fieldGreaterThen("Дата начала", {date: `01-01-${today.getFullYear()}`})
.fieldLessThen("Дата окончания", {date: `01-01-${today.getFullYear()+1}`}),
["Дата начала", "Дата окончания"],
{activeOnly: false}
);
if (!already_taken.tasks || already_taken.tasks.length == 0) return null;
let taken_days = 0;
for (let i in already_taken.tasks) {
if (!already_taken.tasks[i].fields[0] || !already_taken.tasks[i].fields[1]) continue;
taken_days += daysBetween(
new Date(already_taken.tasks[i].fields[0].date),
new Date(already_taken.tasks[i].fields[1].date)
) + 1;
}
if (taken_days + this_time > max)
return {
errorMessage: `Уже использовано ${taken_days} дней. Осталось ${max - taken_days}. Превышение на ${this_time + taken_days - max}`
};
return null;
});
Фильтрация значений
Фильтрация справочника
Чтобы в поле «Город» показывались только города выбранного региона, используйте getCatalog с серверным фильтром и setFilterAsync. Полный пример кода, описание исходных справочников и объяснение результата приведены в статье Фильтрация элементов.
Фильтрация значений поля типа Форма
Скрипт фильтрует список задач в поле «contragent» (поле типа Форма): отбираются задачи, созданные по связанной форме, в которых в поле «Менеджер» указан тот же пользователь, что и в поле «manager» исходной формы.
form.onChange(["manager"], true)
.setFilter("contragent", state => {
const [manager] = state.changes;
if (!manager?.person_id) return null;
return {
filters: [{
fieldName: "Менеджер",
value: manager.person_id
}]
}
});