System Opero

Klient prosi o zmianę jednej liczby - czyli o utrzymaniu automatyzacji

Automatyzacje w systemach często mają małą barierę wejścia - jednak utrzymanie ich to zupełnie inna para kaloszy. Kilka słów o trzech wzorcach, które spotkaliśmy na wdrożeniach oraz decyzje projektowe, jakie z tego wyszły w Opero.

Konrad JarosińskiKonrad Jarosiński · Tech Lead
11 min czytania
Graf reguły akceptacji faktury kosztowej w edytorze Opero

Zaktualizowano 31 sierpnia 2026

Próg akceptacji faktury kosztowej stoi na pięciu tysiącach. Klient chce dziesięć. Dzwoni w czwartek, bo od poniedziałku zaczyna się nowy kwartał i zarząd podniósł limity.

Z jego perspektywy to jest zmiana wielkości przycisku w telefonie. Jedna liczba, jedno pole, dwie minuty.

Wiem, jak to się kończy, bo widziałem to wystarczająco wiele razy. Zgłoszenie trafia do kolejki. Ktoś musi otworzyć plik ze skryptem, znaleźć właściwe miejsce, zrozumieć kod dookoła i mieć odwagę go ruszyć. Potem to przetestować, czyli w praktyce uruchomić na produkcji i patrzeć, co się stanie. Dwa tygodnie, jeśli nikt akurat nie jest na urlopie.

To jest moment, w którym platforma low-code przestaje być low-code. Wszystko inne dało się wyklikać. Formularze, pola, widoki, raporty, uprawnienia. A potem przychodzi automatyzacja i nagle znowu potrzebny jest programista.

Ten tekst jest o tym, dlaczego tak się dzieje. I o tym, co z tym zrobiliśmy w Opero.

W przeszłości zdarzało się konfigurować warstwę automatyzacji na trzech różnych systemach klasy BPM - i poza samą instalacją i konfiguracją, lwią częścią pracy później jest utrzymanie. To nie są wnioski z demo ani z materiałów producenta. Wszystko poniżej pochodzi z trzeciego miesiąca po wdrożeniu, bo dopiero wtedy widać, co się naprawdę kupiło.

Żeby nie mówić ogólnikami, będę wracał do jednego procesu. Faktura kosztowa wpada do systemu. Do pięciu tysięcy od sprawdzonego dostawcy idzie prosto do księgowości. Wyżej wymaga akceptacji kierownika. Powyżej dwudziestu tysięcy potrzebna jest druga akceptacja. Cisza przez trzy dni robocze uruchamia przypomnienie, przez pięć eskalację do przełożonego. Faktura, do której nie ma zamówienia, idzie ścieżką wyjaśnienia. Nic egzotycznego. Prawie każda firma ma coś takiego, tylko z innymi kwotami.


Przedstawię, jak ten, z pozoru prosty proces wygląda w różnych systemach do BPM.

Pierwsza droga: wszystko mieści się w jednej formule

Najłagodniejsze z trzech podejść wygląda jak arkusz kalkulacyjny. Logikę pisze się formułą, warunek w warunku, funkcja JEŻELI zagnieżdżona kilka razy, całość w jednym polu.

Muszę oddać temu sprawiedliwość: próg wejścia jest naprawdę niski. Osoba, która zna arkusz, pisze pierwszą regułę tego samego dnia, bez szkolenia i bez naszej pomocy. Jest to w miarę zgodne z filozofią low-code i tutaj się czepiać nie będę. Jednak...

Kłopot zaczyna się wtedy, gdy proces przestaje być prosty. Nasza faktura ma trzy progi kwotowe, sprawdzenie dostawcy, sprawdzenie zamówienia i dwie ścieżki czasowe. To wszystko ląduje w jednym wyrażeniu, którego po pół roku nikt nie chce dotykać. Nie da się go obejrzeć etapami, bo etapów nie ma. Nie da się sprawdzić, którą gałęzią poszło konkretne wykonanie, bo gałęzie są nawiasami. Kiedy faktura na dwanaście tysięcy pójdzie tam, gdzie nie powinna, zostaje czytanie formuły i liczenie nawiasów wzrokiem.

Jest jeszcze drugie ograniczenie, mniej oczywiste. W takich systemach zapytania służą do wyświetlania danych, nie do ich przekształcania. Więc każda logika działająca na zbiorze, choćby banalne „znajdź wszystkie faktury bez akceptacji starsze niż trzy dni”, wraca do tej samej formuły i jeszcze ją wydłuża.

Świetne narzędzie do prostych i średnich automatyzacji. Przy zaawansowanych zamienia się w problem.

Druga droga: ściana kodu

Na drugim biegunie nie ma warstwy wizualnej w ogóle. Automatyzacja to plik napisany we własnym języku producenta, zwykle zbliżonym do JavaScriptu, odpalany harmonogramem albo zdarzeniem.

Sufit możliwości jest tu praktycznie nieograniczony. Nasz proces akceptacji to godzina pracy dla dobrego programisty i żadnej walki z narzędziem. Jeśli firma ma zespół techniczny i traktuje platformę jako środowisko wykonawcze, to jest sensowny wybór.

Tylko że próg wejścia jest wysoki, a próg utrzymania jeszcze wyższy. Po roku nikt poza autorem nie wie, co ten kod robi, a autor zwykle siedzi już przy innym projekcie albo w innej firmie. Klient nie zmieni sam niczego. I tu wracamy do czwartkowego telefonu z początku tekstu, bo zmiana pięciu tysięcy na dziesięć wymaga dokładnie tej samej ścieżki co zmiana całego procesu.

To buduje zaawansowane logiki i rozjeżdża się z ideą szybkiego dostarczania aplikacji. W praktyce jest to programowanie, tylko w gorszym edytorze niż zwykłe środowisko programistyczne.

Trzecia droga: prosto do bazy

Trzecie podejście jest najbardziej bezpośrednie. Konfiguruje się akcje, grupuje w zadania agenta, podpina harmonogram, a wykonanie to polecenia SQL na żywych tabelach. Łącznie z zapisem i wstawianiem.

Swoboda jest ogromna. Osoba znająca SQL zrobi tu wszystko, czego potrzebuje, i zrobi to szybko.

Tyle że warstwa konfiguracji ma pełne prawo zapisu do produkcyjnych tabel, a jedynym zabezpieczeniem jest uwaga człowieka piszącego zapytanie. Jeden nieprecyzyjny warunek i mamy incydent. Gorsze jest to, co dzieje się potem, a właściwie to, co się nie dzieje: taka operacja omija walidację pól, uprawnienia i historię zmian, bo działa poniżej nich. Zmiana nie ma autora. W historii rekordu nie widać nic.

To jest jedyna rzecz w całym tym tekście, którą rozumie natychmiast każdy, niezależnie od zaplecza technicznego. Ktoś konfigurujący automatyzację może skasować dane produkcyjne, a system o tym nie opowie.

Do tego dochodzą dwie rzeczy mniejsze, ale uciążliwe. Przy rozbudowanych logikach robi się kosztownie, bo każda operacja uderza w bazę osobno. I praktycznie jedynym wyzwalaczem jest harmonogram. Nasza eskalacja po trzech dniach zadziała bez problemu, ale skierowanie faktury do akceptacji „od razu po dodaniu” wymaga odpytywania bazy co kilka minut i sprawdzania, czy coś się pojawiło. Reakcja natychmiastowa nie istnieje. Istnieje krótszy interwał.

Trzy drogi, jeden kompromis

Kiedy się to zestawi, widać ten sam układ w trzech wariantach. Warstwy automatyzacji zwykle wybierają dwa z trzech: niski próg wejścia, wysoki sufit możliwości i niski koszt utrzymania. Pierwsza droga oddaje sufit. Druga oddaje próg wejścia. Trzecia oddaje bezpieczeństwo i spokój.

Jeśli podejmujesz decyzję o platformie, ten kompromis warto przetłumaczyć na trzy pytania, na które i tak odpowiesz sobie za rok. Kto u nas będzie to zmieniał. Czy to udźwignie nasz nietypowy proces. Ile zapłacimy, kiedy coś się zmieni albo przestanie działać.

Projektując reguły w Opero próbowaliśmy nie oddać żadnej z tych trzech rzeczy.

Co z tego wyszło

Reguła jest u nas grafem, nie tekstem. Ma punkt wejścia i krawędzie między krokami, więc rozgałęzienie jest elementem struktury, a nie nawiasem w formule. Nasz proces akceptacji wygląda jak schemat: warunek kwoty, z niego dwie ścieżki, na każdej nazwane kroki. Osoba nietechniczna jest w stanie to przeczytać i powiedzieć, co się dzieje, choć sama by tego nie zbudowała. To jest niższa poprzeczka niż „umie napisać regułę”, ale to właśnie ona decyduje o tym, czy ktoś w firmie znajdzie krok z progiem kwotowym i zmieni w nim liczbę.

ApexShot-2026-08-27_13-50-18.png
Przykładowa reguła w Opero

Kroków jest trzydzieści typów i to nie jest lista dla efektu, tylko konsekwencja jednej decyzji: rzeczy, które robią co innego, mają być osobnymi krokami. Praca na danych to pobranie rekordów z filtrem, utworzenie rekordu, aktualizacja rekordu, kontrahenta, użytkownika albo pojedynczego pola niestandardowego. Sterowanie przepływem to warunek z dwoma wyjściami, przełącznik z wieloma przypadkami, pętla po tablicy, filtr, przekształcenie, agregacja, sortowanie i usuwanie duplikatów. Komunikacja to e-mail, powiadomienie w aplikacji, webhook i krok AI. Do tego pliki, czyli wygenerowanie dokumentu z szablonu i operacje na załącznikach, oraz sterowanie: wywołanie innej reguły, zapis do kontekstu, wpis do logu, oczekiwanie i świadome zatrzymanie przebiegu.

Brzmi to jak dużo i jest dużo. Chodzi o to, że logika, która w pierwszym podejściu jest jedną wielką formułą, tutaj rozkłada się na kilka nazwanych kroków, a każdy z nich ma swój wynik widoczny dla kolejnych i swoje miejsce na schemacie.

Wyzwalaczy jest dwadzieścia dwa i harmonogram to tylko jeden z nich. Utworzenie, zmiana i usunięcie rekordu w dowolnym obiekcie własnym. Zmiana konkretnego pola niestandardowego na użytkowniku, organizacji albo kontrahencie. Przejście workflow, zawężane do konkretnego przejścia albo etapu, i zakończenie workflow. Utworzenie i zmiana kontrahenta. Utworzenie i zmiana faktury sprzedażowej i kosztowej, a także wygenerowanie pliku faktury. Dodanie i zmiana załącznika. Utworzenie użytkownika, jego zmiana i dołączenie do organizacji. Zmiana danych organizacji. Uruchomienie ręczne z interfejsu lub API. I cron.

W praktyce oznacza to, że faktura trafia do akceptacji w chwili utworzenia, a nie przy najbliższym przebiegu harmonogramu. Eskalacja po trzech dniach dalej chodzi z crona, bo tam to jest właściwe narzędzie. Rzecz w tym, żeby harmonogram był jedną z opcji, a nie jedyną.

Kilka wyzwalaczy ma jeszcze jedną własność, o którą sam bym nie zapytał, dopóki mnie nie zabolała. Zmianę rekordu można zawęzić do tego, kto ją wywołał: tylko edycje z interfejsu, tylko zmiany przez API albo jedno i drugie. To jest zabezpieczenie przed sytuacją, w której reguła reaguje na własny zapis i sama się nakręca.

SQL u nas jest, ale nie mieszka w kroku reguły. Istnieje wyłącznie jako nazwane zapytanie z zadeklarowanymi parametrami, przechodzi walidację przy zapisie i jest ograniczone do zakresu konkretnej firmy. Reguła może je wywołać i podać parametry. Nie może go w locie przepisać. Różnica wobec trzeciej drogi nie polega na tym, że u nas nie da się zmienić ani usunąć danych, bo da się. Polega na tym, gdzie leży ryzyko. Tam pomyłka w warunku powstaje w chwili konfigurowania automatyzacji i od razu uderza w produkcję. Tu zapytanie jest osobnym obiektem, który raz powstał, przeszedł walidację i został przejrzany, a jego zasięg jest ograniczony do jednej firmy niezależnie od tego, kto go wywołuje.

Typowe zapisy nie idą przez SQL w ogóle. Zmiana rekordu, utworzenie rekordu, aktualizacja kontrahenta czy pola niestandardowego to osobne kroki, które respektują kontrakt pól, walidację i historię zmian. Kiedy reguła zmienia status faktury, wygląda to w historii rekordu tak samo jak zmiana zrobiona ręcznie. Automatyzacja nie jest niewidzialną ręką działającą pod systemem.

Skrypt też jest, bo bez niego sufit byłby niższy, niż chcemy. Różnica jest w konstrukcji. Lista dostępnych elementów jest zamknięta, a nie tylko czegoś zabrania: skrypt widzi kontekst reguły, funkcje pomocnicze i standardowe narzędzia języka, a wszystko poza tą listą po prostu nie istnieje. Odwołanie do sieci, do plików, do zegara systemowego czy do dynamicznego wykonywania kodu nie przechodzi walidacji, zanim skrypt w ogóle się uruchomi. Do tego pięć sekund limitu czasu, więc żaden skrypt nie zablokuje przebiegu na kwadrans. Funkcje pomocnicze do odczytu danych są ograniczone do organizacji, w której reguła działa.

Skrypt jest więc narzędziem do rzeczy, których nie da się złożyć z kroków, a nie domyślnym sposobem pisania logiki. To ważne rozróżnienie, bo cała druga droga polega właśnie na tym, że skrypt jest tam jedynym sposobem.

Część, o którą nikt nie pyta na demo

Wszystko powyżej dotyczy budowania. Poniżej jest o dniu, w którym coś nie zadziała, a to jest część, o którą nikt nie pyta przy zakupie i wszyscy pytają w trzecim miesiącu.

Regułę testuje się bez ruszania danych. Silnik przechodzi przez graf naprawdę: warunki są liczone, skrypty wykonywane, szablony renderowane, rozgałęzienia wybierane. Ale wszystko, co zmienia stan świata, zostaje przechwycone zamiast wykonane. Żaden e-mail nie wychodzi, żaden rekord nie jest zapisywany, żaden webhook nie leci, żaden dokument nie jest generowany. Na końcu dostajesz trzy rzeczy: status przebiegu, listę tego, co prawdziwe uruchomienie by zrobiło, i kolejność odwiedzonych kroków razem z tym, co każdy z nich zwrócił.

Odczyty przy tym działają realnie, więc test idzie po prawdziwych danych, a nie po wymyślonych liczbach. Jeśli reguła pobiera faktury bez akceptacji, dostaje te, które naprawdę czekają. To jest różnica między testem, który dowodzi, że logika działa, a testem, który dowodzi tylko, że się kompiluje. Dotyczy to każdej reguły, także nocnej, więc nie trzeba czekać do północy, żeby sprawdzić, czy eskalacja działa.

Każde uruchomienie da się potem obejrzeć. W historii jest odtwarzacz, który pokazuje w animacji, którędy poszło konkretne wykonanie: kolejność odwiedzonych kroków, wybraną gałąź na każdym rozwidleniu, dane na wejściu i wyjściu każdego z nich. Pytanie „dlaczego ta faktura poszła do drugiej akceptacji, skoro była na dwanaście tysięcy” przestaje być śledztwem i staje się kliknięciem. Widać warunek, który zadecydował, razem z wartościami, na których pracował.

ApexShot-2026-08-27_13-52-04.png
Odtwarzacz wykonanej reguły

Są przy tym dwie osobne rzeczy i warto je rozróżnić. Odtworzenie historii to oglądanie, niczego nie wykonuje. Odtworzenie reguły to ponowne uruchomienie na tym samym zdarzeniu, tym razem naprawdę, ze wszystkimi skutkami, i używa się go po naprawieniu błędu, żeby dokończyć to, co się nie udało za pierwszym razem. Historia zapisuje, że dany przebieg był powtórzeniem, więc nie miesza się z tym, co zdarzyło się samo. I nie kasujemy jej po trzydziestu dniach. Uruchomienie sprzed pół roku nadal da się otworzyć.

Błąd nie jest u nas cichą porażką. Każdy krok, poza tym, który celowo kończy przebieg, ma osobne wyjście na wypadek błędu i to konfigurujący decyduje, co się wtedy dzieje: zatrzymać regułę, pójść inną ścieżką, powiadomić kogoś i kontynuować, zapisać informację i przejść dalej. Gałąź błędu widzi to, co poszło nie tak, więc powiadomienie może zawierać konkretny powód, a nie samo „coś się nie udało”.

Przy integracjach to jest różnica między systemem, który działa, a systemem, który się zaciął. Jeśli webhook do księgowości nie odpowiada, można ustawić, że faktura i tak idzie do akceptacji, a administrator dostaje powiadomienie z treścią błędu.

Osobno działa bezpiecznik przed zapętleniem. Pętla ma limit iteracji, domyślnie dwadzieścia pięć i najwyżej sto, a każdy krok ma limit odwiedzin w jednym przebiegu. Reguła, która zapętliłaby się w nieskończoność, kończy się jawnym błędem w historii, a nie kręceniem się w kółko na produkcji przez weekend.

Prawo tworzenia i edycji reguł ma administrator systemu, czyli albo ktoś po naszej stronie, albo wyznaczona osoba u klienta. Definicja jest wersjonowana, więc kiedy coś zaczęło działać inaczej od wtorku, da się sprawdzić, czy ktoś we wtorek regułę ruszał.

Krok AI, czyli kto właściwie decyduje o danych

Jest też krok wywołujący model językowy, ale ciekawe w nim jest co innego, niż zwykle się o tym pisze.

Firma podpina własny klucz do wybranego dostawcy, więc to klient decyduje, czyj model dostaje jego dane i na jakich warunkach. My nie stoimy w środku tej relacji.

W konfiguracji kroku wskazuje się przy tym, które elementy kontekstu reguły prompt w ogóle widzi. Nie wychodzi całe środowisko reguły, tylko to, co zostało wskazane palcem. Jeśli krok ma sklasyfikować opis faktury, dostaje opis faktury, a nie dane kontrahenta, które przypadkiem są w kontekście, bo pobrał je wcześniejszy krok.

Można wymusić odpowiedź w zadanej strukturze zamiast swobodnego tekstu, co ma znaczenie, jeśli wynik ma trafić do pola w rekordzie, a nie do wiadomości dla człowieka. I można zdecydować, co się dzieje, gdy model odpowie czymś nieoczekiwanym: zatrzymać regułę albo zapisać błąd i iść dalej. Reszta, czyli kategoryzacja, klasyfikacja, wyciąganie danych z tekstu i przekształcenia, jest dokładnie tym, czego można się spodziewać.

Wracając do czwartku

Nie uważam, że tamte trzy podejścia są złe. Każde rozwiązuje realny problem i każde ma sytuacje, w których jest właściwym wyborem. Twierdzę tylko, że każde ma koszt i że ten koszt da się nazwać. Formuła oddaje sufit. Skrypt oddaje próg wejścia. SQL na żywej bazie oddaje spokój.

Nam zależało, żeby nie oddać żadnej z tych trzech rzeczy. Graf zamiast formuły, żeby dało się to przeczytać. Zdarzenia zamiast samego harmonogramu, żeby reagowało od razu. Zapytania nazwane i zwalidowane zamiast SQL wklejanego w krok, żeby dostęp do danych był policzalny. Piaskownica zamiast pełnego kodu, żeby sufit został, a ryzyko nie. I test przed wdrożeniem plus odtwarzacz po nim, bo to jest cała różnica między „działa na demo” a „działa w trzecim miesiącu”.

A czwartkowy telefon o zmianie progu z pięciu tysięcy na dziesięć kończy się tak, jak klient zakłada, że powinien: ktoś u niego otwiera regułę, znajduje krok z warunkiem kwoty, zmienia liczbę i uruchamia test, żeby zobaczyć, co by się stało, zanim to zapisze. Bez zgłoszenia i bez czekania do poniedziałku.

Powiązane artykuły

O autorze

Konrad Jarosiński

Inżynier i architekt z 15 letnim doświadczeniem.

Wszystkie artykuły

Następny krok

Zobacz, jak to działa na Twoich procesach.

Przejdziemy przez Twoje operacje, pokażemy, jak Opero je odwzoruje, i szczerze powiemy, co pasuje, a co nie.