Як порахувати значення поля в тригері формулою

17 хв

Elbuz сам рахує значення поля для кожного запису: замість постійного «VIP» правило записує «VIP, якщо сума більша за 10 000, інакше звичайний». Зламана формула не зіпсує поле — воно лишиться без змін.

Коли це знадобиться:

  • Тег залежить від суми замовлення — @if вибирає значення за умовою.
  • Потрібна сума з націнкою чи знижкою — @calc рахує з полів документа.
  • Назва завдання має містити клієнта й номер замовлення — @concat склеює текст із полів.
  • Телефон клієнта треба перенести в документ — @field бере значення з картки контрагента.

З чого почати: картка правила → команда «Змінити дані документа» → у значенні поля формула, що починається з @.

Що вміють формули

  • @if — вибирає одне з двох значень за умовою.
  • @calc — рахує арифметику з полів запису.
  • @concat і @field — склеюють текст і переносять значення з одного запису в інший.
  • @json — дістає значення з додаткових полів документа чи контрагента.
  • Вкладені формули — логіка, яку одна функція не виражає.
  • Перевірка при збереженні — зламаний синтаксис не збережеться, помилка на даних не зіпсує поле.

Де це і хто має доступ

Окремого вікна й пункту меню у формул немає. Вони живуть усередині команди правила — у тому самому конструкторі, яким збирається умова, але прочитаному інакше: ліворуч поле, праворуч значення, яке треба записати. Оператор посередині в цьому режимі не використовується. Під конструктором є памʼятка з назвами джерел і чотирма прикладами.

Інші входи
«Автоматичні правила» → олівець на правилі → секція «Команда» → олівець на команді
Право доступу
те саме, що на вікно правил — окремого права у формул немає
Підготувати
правило з командою, яка змінює або створює запис

Шлях від нуля до працюючої формули

  1. Відкрити картку правила й перейти до командиАвтоматичні правила
  2. Вибрати ліворуч поле, яке треба заповнитиНалаштування команди
  3. Написати у значенні формулу, що починається з @Налаштування команди
  4. Натиснути «Зберегти умову» й перевірити на одному записіНалаштування команди
Вікно налаштування команди «Змінити дані документа» з трьома рядками конструктора та памʼяткою про формули
1Поле документа, яке заповнюємо
2Значення — тут пишеться формула
3Памʼятка про синтаксис формул
  1. Ліворуч обирається поле документа, значення якого буде змінено.
  2. Праворуч — значення поля; текст, що починається з @, Elbuz обчислює як формулу.
  3. Памʼятка нижче пояснює синтаксис формул на прикладах @calc, @if, @concat і @json.

Як влаштоване саме правило — подія, умова, порядок виконання команд і захист від повторного спрацювання — розібрано в посібнику з автоматичних правил. Ця стаття тільки про те, що написати у значенні поля.

Як це працює

Коли правило спрацювало, програма бере кожну пару «поле — значення» з команди й дивиться на перший символ значення. Якщо це @ — значення рахується як формула. Якщо ні — записується як є.

Розбір формули завжди однаковий: після @ має стояти назва функції, одразу за нею — дужка, а останній символ значення має бути закриваючою дужкою. Усередині дужок — параметри через кому. Далі програма підставляє дані замість посилань виду джерело.поле й повертає результат.

Помилки ловляться двічі. Перший раз — при збереженні команди: програма проганяє кожну формулу «вхолосту», підставляючи замість будь-якого поля одиницю. Так знаходяться зламаний синтаксис, невідома функція і сторонні символи в @calc — команда не зберігається, а на 6 секунд спливає червоне повідомлення «Умову не збережено — помилка у формулі» з переліком того, що не прийнялося.

Другий раз — коли правило спрацювало на реальному записі. Те, що при збереженні перевірити не можна (поле виявилося порожнім, текстовим замість числа, нульовим дільником), вилазить тільки тут.

У цьому випадку поле не змінюється зовсім — старе значення лишається на місці, а в загальному «Журналі операцій» (Кабінет → Журнал операцій) зʼявляється рядок «Формулу не розібрано, поле не змінено» з назвою правила, команди й самою формулою; номер запису — у колонці «ID обʼєкта».

Плитка «Журнал операцій» у картці документа його не показує: вона відкриває історію змін полів. Решта полів команди записуються як звичайно.

Дві точки, у яких може зламатися формула, і два різні наслідки: у першому випадку не збережеться команда, у другому — мовчки не зміниться поле
НіТакНіТакТакНі: текст замість числа,порожнє поле, ділення нанульЗначення поля в командіПерший символ — «@»?Записується як звичайний текстРозбирається як формулаСинтаксис цілий?Перевірка при збереженні:замість полів підставляєтьсяодиниця«Умову не збережено —помилка у формулі».Команда не зберігаєтьсяКоманда збереженаПравило спрацювало на записі:формула рахується реальнимиданимиОбчислення вдалося?Значення записується в полеПоле лишається зі старимзначенням.У журналі операцій запису —«Формулу не розібрано, поле незмінено»
  • Дія або результат
  • Розвилка: далі шлях залежить від відповіді

Значення, яке починається з @, але не є формулою, програма теж спробує обчислити — і не дасть зберегти команду. Якщо вам треба записати в поле текст на кшталт @shop, поставте перед ним пробіл або будь-який інший символ.

Сім команд, у яких формули працюють

Формула обчислюється не в будь-якому полі правила, а тільки там, де команда записує значення в поле запису:

  • «Змінити дані документа» і «Створити документ»;
  • «Змінити дані контрагента» і «Створити контрагента»;
  • «Створити організацію» і «Змінити дані організації»;
  • «Додати завдання».

У решті команд формул немає зовсім. У «Надіслати листа», «Надіслати SMS» і «Виконати HTTP-запит» дані запису підставляються макросами у фігурних дужках — {Документ: № документа} або коротко {{d.document_number}}, {{pc.name}}, {{cn.name}}. Символ @ там залишиться звичайним текстом. Команда «Запустити процес (Flow)» значень полів не задає взагалі — вона тільки вибирає процес.

Два поля в цих командах поводяться не як усі, і формула на них теж поширюється:

  • поле проводки в командах з документами не записує текст, а проводить документ (як правило проводить документ). Формулу туди не ввести: у конструкторі це список «Так / Ні», а не рядок вводу;
  • поле типу документа в команді «Створити документ» задає, у який тип копіювати. Ввести формулу можна, але не варто: формула, що дала порожньо, мовчки зупинить команду — нічого не створиться.

Так само мовчки зупиняються «Створити контрагента» без імені й «Додати завдання» без назви — це захист від порожніх карток, але виглядає він як «правило не спрацювало».

Звідки формула бере дані

Дані беруться з трьох джерел, і звертаються до них через крапку:

  • document.поле — документ, через який спрацювала подія;
  • contractor.поле — його контрагент (а якщо подія була на контрагенті — сам контрагент);
  • company.поле — ваша організація з документа.

Усі три джерела доступні в усіх семи командах.

Джерела field. у тригерах не існує, хоча воно згадується в старих прикладах. Будь-яке field.щось завжди дасть порожній рядок, а всередині @calc порахується нулем. Джерела user. немає теж.

Порожнім джерело буває й законно: якщо подія піднялася на контрагенті, документа в ній немає, і всі document. дадуть порожньо. Те саме з company., якщо в документі не вказана ваша організація.

Звідки брати імена полів

У лівому списку конструктора поля названі по-людськи, а у формулі потрібне службове імʼя — те саме, що використовується в коротких макросах HTTP-запиту ({{d.document_number}}). Найчастіше потрібні:

  • документ: document_number — номер, document_sum — сума, description — примітка, tag — мітка, delivery_price — вартість доставки, email, phone, custom_field_ext — додаткові поля, document_status_name — статус, contractor_name — назва контрагента;
  • контрагент і організація: name — назва, phones і email — контакти, description — опис, discount_percent — знижка, customer_type — тип клієнта, contractor_group_name — група, code_iin — податковий код.

Імені, якого немає, програма не помітить: document.neisnuiuche тихо дасть порожній рядок. Перевірка при збереженні цього теж не ловить: неіснуюче поле для неї виглядає як звичайне. Перевіряють одним прогоном на тестовому записі — якщо поле заповнилося порожнім, справа майже завжди в імені.

Окремо працює поле терміну в команді «Додати завдання»: крім формул, воно розуміє підстановки дат — {current_date}, {current_date+3day}, {current_date+1week}. Одиниці ті самі, що й в умовах правила: minute, hour, day, week, month, year.

Пʼять функцій і готові формули

@if — умова

Синтаксис: @if(умова, значення_якщо_так, значення_якщо_ні). Умова пишеться строго як джерело.поле оператор значення, і пробіли навколо оператора обовʼязкові. Оператори: equals, contains, >, <, >=, <=, !=.

Будь-яка умова, яку не вдалося розібрати, вважається невиконаною — програма мовчки бере третій параметр. Саме тому @if(document.document_sum>5000, 'VIP', 'Звичайний') без пробілів завжди повертає «Звичайний», хоча виглядає правильно.

contains шукає підрядок з урахуванням регістру: contains 'терміново' не знайде слово «ТЕРМІНОВО». equals порівнює нестрого, тому '5' і 5 для нього однакові.

Окремої перевірки «поле порожнє» немає: пишеться як equals ''. Для тексту це працює, а от нуль у числовому полі порожнім не вважається.

@calc — арифметика

Синтаксис: @calc(вираз). Дозволені цифри, десятковий дріб через крапку, дужки й знаки + - * /. Посилання на поля підставляються значеннями до обчислення, тому @calc(document.document_sum * 1.2) на сумі 1000 дасть 1200.

Три випадки, у яких @calc відмовиться рахувати — команда при цьому не обривається, просто це поле лишиться без змін:

  • у полі текст, а не число: @calc(document.description * 2) дасть помилку «Поле document.description не число»;
  • ділення на нуль: @calc(100 / document.delivery_price), якщо вартість доставки нульова;
  • функції й інші символи: ніяких відсотків та імен функцій — тільки чотири дії.

Кома замість крапки помилки не дасть, але все після коми буде відкинуто: @calc(document.document_sum * 1,2) порахує суму, помножену на 1. Дріб пишіть тільки через крапку.

Незаповнене поле помилкою не вважається: воно рахується нулем. @calc(document.document_sum + contractor.discount_percent) на контрагенті без знижки поверне просто суму документа.

@concat — склеїти текст

Синтаксис: @concat(частина, частина, …), скільки завгодно частин. Текст береться в одинарні лапки, посилання на поля — без лапок. Пробіли всередині лапок зберігаються, між параметрами — ні.

@concat('Замовлення від ', contractor.name, ' на суму ', document.document_sum) дасть «Замовлення від ТОВ Ромашка на суму 1000».

@json — дістати значення з JSON

Синтаксис: @json(джерело.поле, 'ключ'). Так читаються поля, у яких лежить JSON — насамперед додаткові поля документа й контрагента. Якщо в полі {"16":"test1","17":"443355"}, то @json(document.custom_field_ext, '17') поверне 443355.

Читається тільки верхній рівень: вкладеність через крапку не підтримується. Якщо ключа немає або в полі не JSON, результат — порожній рядок, і ніякої помилки при цьому не буде.

@field — просто значення поля

Синтаксис: @field('джерело.поле'), шлях обовʼязково в лапках. Це найкоротший спосіб перенести значення з одного запису в інший: @field('contractor.phones') покладе в поле телефон контрагента.

Без крапки у шляху (@field('name')) функція поверне порожньо — джерело вказувати обовʼязково.

Формула всередині формули

Гілки @if і аргументи @concat, @json, @field самі можуть бути формулами. Так збирається логіка, яка однією функцією не виражається:

  • @if(contractor.customer_type equals 'VIP', @calc(document.document_sum * 9 / 10), document.document_sum) — знижка десять відсотків тільки VIP-клієнтам;
  • @concat('Клієнт: ', contractor.name, @if(document.document_sum > 5000, ' (великий)', '')) — приписка тільки до великих замовлень.

Рахується лише та гілка, яку вибрала умова. Тому у другій гілці можна залишити дію, яка на цьому записі заздалегідь неможлива — наприклад ділення на поле, яке в частини записів нульове: поки умова туди не заводить, помилки не буде.

Готові формули

Усе нижче перевірене й працює як написане.

  • Позначити великі замовлення: поле «Теги» → @if(document.document_sum >= 10000, 'VIP', 'Звичайний').
  • Термінові за приміткою: поле «Теги» → @if(document.description contains 'терміново', 'Терміново', 'Звичайно').
  • Перенести телефон клієнта в документ: поле «Телефон» → @field('contractor.phones').
  • Зібрати назву завдання: поле «Назва задачі» → @concat('Передзвонити: ', contractor.name, ' · ', document.document_number).
  • Дістати код із додаткових полів: @json(document.custom_field_ext, '17').
  • Порахувати суму з націнкою двадцять відсотків: @calc(document.document_sum * 1.2).
  • Скопіювати статус оплати в примітку доставки: @concat('Оплата: ', document.payment_status_name).
  • Знижка тільки постійним клієнтам: @if(contractor.customer_type equals 'Постійний', @calc(document.document_sum * 0.95), document.document_sum).
  • Очистити поле: значення null без жодного @ — програма запише порожньо навмисно.

Кілька команд пишуть в одне поле

Перезапису програма не забороняє і не попереджає про нього: в полі лишається те, що записали останнім. Хто саме останній, залежить від того, де стоять конкурентні значення.

  • Два рядки з тим самим полем в одній команді. Рядки розбираються згори вниз, і записується значення нижнього. Якщо формула нижнього рядка зламалася, запишеться значення верхнього.
  • Кілька команд одного правила. Команди виконуються по черзі за полем «Порядок виконання», і кожна записує свої поля окремо — в полі лишиться значення команди, що виконалася останньою. Важливо інше: усі формули правила рахуються з даних запису, прочитаних на початку спрацювання правила. Якщо перша команда записала в примітку «VIP», то document.description у формулі другої команди того самого правила поверне стару примітку, а не «VIP».
  • Два різні правила на одну подію. Правила виконуються по черзі за полем «Порядок виконання», а при однаковому порядку — за назвою. Кожне наступне правило перечитує запис заново, тож його умова й формули вже бачать те, що записали попередні. В полі лишається значення правила, що виконалося останнім.

Звідси робочий прийом: якщо формула має спиратися на значення, яке записує інша команда, винесіть її в окреме правило на ту саму подію з більшим «Порядком виконання».

Небезпечні місця

Пробіл у кінці значення. Формула має закінчуватися дужкою: якщо після неї залишився пробіл, розбору не буде. Такий пробіл легко з'являється при копіюванні, а на вигляд його не видно — зате команда не збережеться, і в повідомленні ви побачите свою формулу цілком.

Умова без пробілів навколо оператора. Це єдина помилка, яку перевірка при збереженні пропускає: @if(document.document_sum>5000, …) — синтаксично правильна формула, вона просто завжди йде в гілку «інакше». Помітити можна лише за результатом.

Формула в полі, яке заповнюється зі списку. Статус документа, тип оплати, валюта, проводка — у конструкторі це випадні списки, а не рядок вводу: формулу туди не набрати. Формули пишуться тільки в текстових і числових полях.

І найтихіше з усього: команда, у якій формула зламалася на реальному записі, все одно вважається виконаною. Правило запамʼятає, що вже відпрацювало на цьому документі, і вдруге його не чіпатиме — навіть після того, як формулу виправлять. Тому перевіряти виправлення треба на новому записі, а не на тому самому.

Якщо формула вже записала не те

Попереднього значення поля програма не зберігає: у журналі видно, що команда спрацювала, але не видно, що було в полі до неї. Кнопки «повернути як було» немає, і виправлення — це запис правильного значення поверх неправильного.

  1. Вимкніть правило тумблером «Активність», щоб воно не зачепило нові записи, поки ви виправляєте.
  2. Знайдіть зачеплені записи. Відкрийте «Кабінет» → «Журнал операцій» і в колонці «Інформація» відфільтруйте рядки за текстом Трігер #номер назва правила — саме так починається рядок про кожне виконання команди. Назву додавайте обовʼязково: фільтр шукає входження, і Трігер #7 без назви знайде також правила #70, #71 і далі. Номери документів чи контрагентів — у колонці «ID обʼєкта».
  3. Розберіть знайдене. Рядки, що починаються з «Не виконано!», — команда не відпрацювала. Рядки з «Формулу не розібрано, поле не змінено» — поле лишилося старим. Решта — записи, у які формула записала значення. У команд «Створити документ» і «Додати завдання» рядок стоїть на вихідному записі й закінчується номером створеного: document_created #… або task_created #…. Чи проведено створений документ, з цього рядка не видно — це перевіряють у самому документі.
  4. Виправте формулу. Просто зберегти виправлену команду замало: правило памʼятає, на яких записах кожна команда вже відпрацювала, і на них вона більше не запуститься.

Щоб правило саме переписало поле на вже зачеплених записах, видаліть команду й додайте її заново з правильною формулою. Разом із командою стираються її позначки «вже виконано», тож нова команда відпрацює на кожному записі при наступній його події — якщо запис підходить під умову правила. Видалення всього правила так само стирає позначки всіх його команд.

Сценарії

Позначити великі замовлення, не стерши теги менеджера

Команда «Змінити дані документа», поле «Теги» → @if(document.document_sum >= 10000, '+VIP', '+'). Значення, що починається з плюса, дописує тег до тих, що вже стоять у документі, а самотній + лишає теги як є. Без плюса ('VIP') формула замінить усі теги документа одним «VIP», а порожній результат зітре їх зовсім.

Чого не станеться: якщо суму документа згодом змінять, тег на цьому документі не перерахується — команда вже відпрацювала на ньому й вдруге не запуститься.

Перенести телефон клієнта в документ

Команда «Змінити дані документа», поле «Телефон» → @field('contractor.phones'). У документ запишеться телефон з картки контрагента. Чого не станеться: перевірки «а чи є там телефон» немає. Якщо в картці контрагента телефон не заповнений, формула дасть порожньо, і телефон, що вже був у документі, буде стертий. Коли таке можливо, додайте в умову правила перевірку, що телефон у контрагента є.

Поставити менеджеру завдання передзвонити

Команда «Додати завдання»: «Назва задачі» → @concat('Передзвонити: ', contractor.name, ' · ', document.document_number), «Термін виконання» → {current_date+1day}. Завдання зʼявиться картою на першій активній дошці органайзера в її першій колонці (якщо поля «Дошка (ID, порожньо — перша активна)» і «Колонка (ID, порожньо — перша)» не заповнені) і буде привʼязане до документа.

У Кабінет → Журнал операцій рядок про виконання закінчиться на task_created # і номер картки. Термін записується датою без часу, навіть якщо в підстановці стоїть hour чи minute.

Чого не станеться: якщо назва вийшла порожньою або в органайзері немає жодної активної дошки, завдання не створиться, а в журналі буде рядок «Не виконано!». Позначки «виконано» тоді немає, тож команда спробує ще раз при наступній події на цьому документі.

Що робити, коли формула не спрацювала

«Умову не збережено — помилка у формулі»
формула не розібралася. Перевірте: перший символ @, останній — ), назва функції з пʼяти дозволених, немає пробілу в кінці. У самому повідомленні перелічені формули, які не прийнялися.
Поле лишилося з колишнім значенням
формула зламалася вже на записі. Причина — рядком «Формулу не розібрано, поле не змінено» в Кабінет → Журнал операцій (не в плитці «Журнал операцій» картки документа). Найчастіше це @calc над текстовим полем або ділення на нуль.
Завжди підставляється друге значення з @if
умова не розібралася й вважається невиконаною. Найчастіше через відсутні пробіли навколо оператора або через невірне імʼя поля.
@json повертає порожньо
або ключа немає на верхньому рівні, або в полі не JSON. Вкладені ключі функція не читає.
Документ не створився
формула в полі типу документа дала порожньо. Тип має бути заданий обовʼязково, і краще — постійним значенням.

Часті запитання

У яких полях правила можна писати формули?

Тільки у значеннях полів семи команд: «Змінити дані документа», «Створити документ», «Змінити дані контрагента», «Створити контрагента», «Створити організацію», «Змінити дані організації» та «Додати завдання». В умові правила, у листі, SMS і HTTP-запиті формули не працюють.

Як дізнатися, що у формулі помилка?

Зламаний синтаксис видно одразу: команда не збережеться, а на 6 секунд спливе червоне повідомлення з переліком формул, які не прийнялися. Помилки на даних — ділення на нуль, текст замість числа — потрапляють у Кабінет → Журнал операцій рядком «Формулу не розібрано, поле не змінено».

Чи рахує @calc дробові числа?

Так: @calc(document.document_sum * 1.2) на сумі 1000 дасть 1200. Дріб пишеться через крапку. Незаповнене поле у виразі рахується нулем, а текст у полі і ділення на нуль дають помилку — поле тоді лишається без змін.

Чому не працює user.поле з прикладів?

Такого джерела в тригерах немає — як і field.. Доступні лише document., contractor. і company..

Чи є функції дати, округлення чи заміни тексту?

Ні. Є лише пʼять функцій: @if, @calc, @concat, @json, @field. Позицій документа (document. бачить тільки шапку), залишків на складі й інших записів формула теж не читає.

Чи працюють тут формули з цін і полів каталогу — CASE, IF, функції MySQL?

Ні, це інший механізм з іншим синтаксисом. Він описаний у статтях формули ціни і формули полів каталогу; у тригерах працюють тільки пʼять функцій з @.

Суміжні теми

Чи була стаття корисною?