Примеры скриптов
- Скопировать значение одного поля в другое
- Вычислить сумму (разницу, процент) нескольких полей
- Сделать поле невидимым
- Сделать поле невидимым, начиная с определённого этапа
- Вывести значение колонки справочника
- Выбор значения из справочника по полю с типом Контакт
- Валидация: дата окончания не раньше даты начала
- Валидация: заполнено хотя бы одно поле
- Перенос крайнего срока в зависимости от приоритета
- Установка срока за N дней до указанной даты
- Автоматическая смена статусов задач при редактировании полей
- Автоматическое заполнение срока SLA
- Скрываем поле, если письмо пришло не от заданного адреса
- Фильтрация справочника
- Установка даты в рабочих днях
- Фильтрация поля типа Форма
Скопировать значение одного поля в другое
Копируем значение из поля 'Поле-источник' в поле 'Текстовое поле'.
form.onChange(['Поле-источник'], true) .setValue('Текстовое поле', state => { const [value] = state.changes; if (!value) return null; return value.text; });
Вычислить сумму (разницу, процент) нескольких полей
В этом примере скрипт прибавляет премию сотрудника к его окладу и рассчитывает НДФЛ от полученной суммы. Затем вычитает НДФЛ из этой суммы и выводит итоговую выплату за месяц.
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]; });
Сделать поле невидимым
В этом примере поле 'Оптовая скидка' скрыто, если значение в поле 'Количество' не превышает 99.
form.onChange(['Количество'], true) .setVisibility(['Оптовая скидка'], state => { const [quantity] = state.changes; if (!quantity) return null; const num = quantity.value; return num > 99; });
Сделать поле невидимым, начиная с определённого этапа
В этом примере поле 'Клиент' будет скрыто, начиная со второго этапа.
form.onChange([''], true) .setVisibility (['Клиент'], state => { return state.currentStep < 2; });
Вывести значение колонки справочника
Здесь 'Справочник' — название поля с вашим справочником, 'Колонка' — название колонки справочника, а 'Текст' - поле типа Текст, в котором будет сохранено значение.
form.onChange(['Справочник']) .setValue('Текст', state => { const [item] = state.changes; if (!item || !item.columns) return null; return item.columns['Колонка']; });
Выбор значения из справочника по полю с типом Контакт
Иногда требуется подставлять в заявку ФИО сотрудника в родительном падеже. Простой пример — заявление на отпуск. Чтобы Pyrus делал это автоматически, создаём справочник со списком сотрудников и колонкой с их ФИО в родительном падеже. И подключаем к форме такой скрипт:
let catalogItems = null; form.getCatalog(ID справочника).then(items => { catalogItems = items; }); form.onChange(['Отпускник']) .setValue('От (ФИО):', state => { const [contactField] = state.changes; console.log(state) if (!catalogItems || !contactField || !contactField.person_id) return null; const filteredRow = catalogItems .find(item => item.columns['Сотрудник'] == `${contactField.first_name} ${contactField.last_name}` ); console.log(filteredRow, catalogItems, contactField.person_id) return filteredRow ? filteredRow.columns['ФИО Род'] : null; });
В этом примере:
- 'Отпускник' — название поля типа Контакт;
- 'Сотрудник' и 'ФИО Род' — название колонок справочника, в котором мы ищем значение по выбранному полю;
- 'От (ФИО):' - поле типа Текст, в котором сохраняем найденное значение из справочника.
Валидация: дата окончания не раньше даты начала
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; });
Перенос крайнего срока в зависимости от приоритета
C возможностью установки произвольного срока.
form.onChange(['Высокий приоритет', 'Перенос даты']) .setValue('Срок', state => { const [checkmark, customDue] = state.changes; if (customDue && customDue.date) return {date: customDue.date}; if (!checkmark) return null; 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()}]; });
Автоматическая смена статусов задачи при редактировании полей
Скрипт подойдёт тем, кто в рамках задачи работает с партнёрами. В нашем примере статус задачи будет меняться на «В работе», если партнёр назначил ответственного в поле «Ответственный за решение».
//Индивидуальный номер организации, которая редактирует форму. Чтобы узнать ID, напишите на support@pyrus.com. const orgId = 111111; form.onChange([], true) .setVisibility(['Открыта / Завершена'], state => false ); form.onChange([], true) .setStatus(state => { if (state.commenter && state.commenter.organization_id !== orgId) return {choice_name: 'В работе'}; }); form.onChange(['Ответственный за решение']) .setStatus(state => { const [currVal] = state.changes; const [prevVal] = state.prev; if (!prevVal && currVal) return {choice_name: 'В работе'}; });
Автоматическое заполнение срока 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; } }
Скрываем поле, если письмо пришло не от заданного адреса
Если письмо пришло не от mail@example.com — скрываем поле «Тип заявки».
form.onChange(['Email'], true) .setVisibility(['Тип заявки'], state => { const [email] = state.changes; return email && email.text == 'mail@example.com'; });
Фильтрация справочника
Этот скрипт позволяет фильтровать список городов по выбранному региону. Другой пример — при выборе отдела показывать только статьи расходов, относящиеся к этому отделу.
let catalogItems = null; form.getCatalog("Города по регионам").then(items => { catalogItems = items; }); form.onChange(["Регион"]).setFilter("Город", state => { const [region] = state.changes; if (!catalogItems || !region || !region.columns) return null; const regionCol = region.columns["Регион"]; const filtered = catalogItems .filter(item => item.columns["Регион"] === regionCol) .map(item => item.columns["Город"]); return filtered.length > 0 ? { values: filtered } : null });
Установка даты в рабочих днях
Этот скрипт позволяет задавать дату с учётом выходных дней. Даты выходных и рабочих дней берутся из справочника.
var catalogHolidayItems = null; var catalogWorkingItems = null; // Получаем массив дат из справочника "Даты перенос" со столбцами "Даты перенос", "Тип" form.getCatalog("Даты перенос").then(items => { if (!items) return null; catalogHolidayItems = items .filter(item => item.columns["Тип"] == 'Выходной') .map(item => item.columns["Даты перенос"]); catalogWorkingItems = items .filter(item => item.columns["Тип"] == 'Рабочий') .map(item => item.columns["Даты перенос"]); }); // Поиск даты в массиве function containsDate(date, array) { for (let i = 0; i < array.length; i++) { if (date.getTime() == array[i].getTime()) { return true; } } return false; } // Проверить является ли дата выходным днем function isWeekend(date) { return date.getDay() == 0 || date.getDay() == 6; } // Количество и список выходных и праздничных дней form.onChange(['Дата','Дата окончания']) .setValues(['Список выходных дней', 'Число выходных между датами'], state => { const [startDateField, endDateField] = state.changes; if (!startDateField || !endDateField) return null; const startDate = new Date(startDateField.date); const endDate = new Date(endDateField.date); const holidaysArray = catalogHolidayItems.map(date => new date(d + 'T00:00:00Z')); const workingDaysArray = catalogWorkingItems.map(date => new date(d + 'T00:00:00Z'); const textArray = []; const monthNames = 'января,февраля,марта,апреля,мая,июня,июля,августа,сентября,октября,ноября,декабря'.split(','); while (startDate <= endDate) { if ((isWeekend(startDate) && !containsDate(startDate, workingDaysArray)) || containsDate(startDate, holidaysArray)) { const dateText = startDate.getDate().toString() + ' ' + monthNames[startDate.getMonth()] + ' ' + startDate.getFullYear().toString() + ' г.'; textArray.push(dateText); } startDate.setDate(startDate.getDate() + 1); } let text = ''; if (textArray.length == 1) { text = textArray[0]; } else if (textArray.length > 1) { text = textArray.slice(0, textArray.length - 1).join(', ') + ' и ' + textArray[textArray.length - 1]; } return [text, textArray.length]; }); // Установка даты в рабочих днях form.onChange(['Дата','Кол-во дней']) .setValues(['Дата + Кол-во рабочих дней'], state => { const [startDateField, daysNum] = state.changes; if (!startDateField || !daysNum) return null; const startDate = new Date(startDateField.date); const endDate = new Date(startDateField.date); endDate.setDate(endDate.getDate() + daysNum.value); const holidaysArray = catalogHolidayItems.map(date => new Date(date + 'T00:00:00Z')); const workingDaysArray = catalogWorkingItems.map(date => new Date(date + 'T00:00:00Z')); do { if ((isWeekend(startDate) && !containsDate(startDate, workingDaysArray)) || containsDate(startDate, holidaysArray)) { endDate.setDate(endDate.getDate() + 1); } startDate.setDate(startDate.getDate() + 1); } while (startDate <= endDate); return [{date: endDate.toDateString()}]; });
Фильтрация поля типа Форма
В этом примере скрипт позволяет выполнить фильтрацию полей типа Форма, чтобы отсортировать заявку, соответствующую запросу.
form.onChange(["Текст"]).setFilter("Bug 143331863", state => { const [region] = state.changes; if (!region || !region.value) return null; return { filters: [ {fieldCode: "code_field", value: 3}, {fieldName: "name_field", value: "12"} ] } });