Паперові погодження тривають тижнями. Документи губляться, підписи підробляють, співробітники витрачають час на постійні нагадування. Ми розробляємо цифрові workflow погодження, які припиняють цей хаос. Наш движок вбудовується в сайт або CRM, автоматично направляє документи за заданими маршрутами, контролює терміни та веде повний аудит. Жодних «загубилося в пошті» — все прозоро в одному вікні. За 5 років ми реалізували 50+ проєктів, скоротивши час погодження в середньому в 3 рази. Докладніше про концепцію workflow можна прочитати на Wikipedia.
Проблеми, які вирішує workflow погодження
Якщо керівник у відрядженні, процес зупиняється. Наш движок автоматично ескалює завдання заступнику або перенаправляє за правилами. Тайм-аути налаштовуються в годинах — якщо відповіді немає, система нагадує, а потім передає вище. Ручний контроль забирає години: співробітники відстежують статуси вручну. Ми даємо особистий кабінет з timeline, де видно кожен крок: хто, коли і що вирішив. Ініціатор бачить прогрес, погоджувачі — дедлайн. Помилки та дублі виключаються: workflow жорстко задає маршрут з перевіркою ролей. В одному проєкті ми скоротили кількість помилок на 90%. Інтеграція з ЕЦП (електронним підписом) реалізується через API підписантів, підтримуються сертифікати КЕП та НЕП. Перехід на електронний документообіг дає повну прозорість — це і є система підписання документів на сайті.
Як ми будуємо гнучкий workflow?
Використовуємо перевірений стек: TypeScript + Node.js (Nest.js) на бекенді, React з TypeScript на фронтенді. Для зберігання — PostgreSQL з JSONB для шаблонів кроків. Движок станів реалізований як окремий мікросервіс з чіткими транзакціями.
Модель даних — шаблони workflow, екземпляри для кожного документа та завдання погодження. Кожне завдання прив'язане до кроку, виконавця та тайм-ауту. JSONB у шаблоні дозволяє гнучко описувати кроки: тип (послідовний/паралельний), умови переходу, ескалацію.
-- Шаблони workflow CREATE TABLE workflow_templates ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name VARCHAR(200), description TEXT, steps JSONB NOT NULL, -- Масив кроків з конфігурацією created_by UUID REFERENCES users(id) ); -- Екземпляр workflow для конкретного документа CREATE TABLE workflow_instances ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), template_id UUID REFERENCES workflow_templates(id), document_id UUID REFERENCES documents(id), initiator_id UUID REFERENCES users(id), current_step INT DEFAULT 1, status VARCHAR(50) DEFAULT 'in_progress', -- in_progress, approved, rejected, cancelled metadata JSONB DEFAULT '{}', created_at TIMESTAMPTZ DEFAULT NOW(), completed_at TIMESTAMPTZ ); -- Завдання погодження CREATE TABLE workflow_tasks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), instance_id UUID REFERENCES workflow_instances(id), step_number INT NOT NULL, assignee_id UUID REFERENCES users(id), assignee_role VARCHAR(100), -- Альтернатива assignee_id для динамічних ролей task_type VARCHAR(50), -- 'approve', 'sign', 'review' status VARCHAR(50) DEFAULT 'pending', -- pending, approved, rejected, delegated comment TEXT, due_at TIMESTAMPTZ, completed_at TIMESTAMPTZ, completed_by_id UUID REFERENCES users(id) -- Якщо делегував ); Движок обробляє рішення: approve — перевіряє паралельний крок (чи всі схвалили), потім переходить до наступного кроку або завершує workflow. reject — зупиняє процес або повертає на доопрацювання. request_changes — надсилає документ ініціатору з коментарем.
class WorkflowEngine { async processDecision( taskId: string, decision: 'approve' | 'reject' | 'request_changes', comment: string, userId: string ) { const task = await db.workflowTasks.findOne(taskId, { include: 'instance.template' }); if (task.assigneeId !== userId) throw new Error('Not authorized'); await db.workflowTasks.update(taskId, { status: decision, comment, completedAt: new Date(), }); await auditLog.record({ action: `task.${decision}`, userId, taskId, instanceId: task.instanceId, }); switch (decision) { case 'approve': await this.onTaskApproved(task); break; case 'reject': await this.onTaskRejected(task); break; case 'request_changes': await this.returnToInitiator(task, comment); break; } } private async onTaskApproved(task: WorkflowTask) { const instance = task.instance; const template = JSON.parse(instance.template.steps); const currentStep = template[task.stepNumber - 1]; // Паралельний крок: перевіряємо чи всі в цьому кроці схвалили if (currentStep.type === 'parallel') { const stepTasks = await db.workflowTasks.findAll({ instanceId: instance.id, stepNumber: task.stepNumber, }); const allApproved = stepTasks.every(t => t.status === 'approve'); const anyRejected = stepTasks.some(t => t.status === 'reject'); if (anyRejected) return this.onTaskRejected(task); if (!allApproved) return; // Чекаємо інших } // Переходимо до наступного кроку const nextStep = template[task.stepNumber]; // Наступний елемент if (!nextStep) { // Всі кроки пройдено — workflow завершено await this.completeWorkflow(instance.id); } else { await this.activateStep(instance.id, nextStep, task.stepNumber + 1); } } private async activateStep(instanceId: string, step: WorkflowStep, stepNumber: number) { await db.workflowInstances.update(instanceId, { currentStep: stepNumber }); const assignees = await this.resolveAssignees(step); const dueAt = step.deadlineHours ? addHours(new Date(), step.deadlineHours) : null; for (const assignee of assignees) { const task = await db.workflowTasks.create({ instanceId, stepNumber, assigneeId: assignee.id, taskType: step.taskType, dueAt, }); await notifyAssignee(assignee, task); } } } Як працює делегування та ескалація?
Погоджувач може передати завдання колезі з коментарем. Система закриває вихідне завдання та створює нове для делегата. Всі делегування фіксуються в аудит-лозі.
async function delegateTask(taskId, delegateToId, reason, requesterId) { const task = await db.workflowTasks.findByPk(taskId); if (task.assigneeId !== requesterId) throw new Error('Not authorized'); // Закриваємо поточне завдання await db.workflowTasks.update(taskId, { status: 'delegated', comment: `Делеговано: ${reason}`, completedAt: new Date(), }); // Створюємо нове для делегата await db.workflowTasks.create({ ...task.toJSON(), id: undefined, assigneeId: delegateToId, status: 'pending', completedAt: null, metadata: { delegatedFrom: task.assigneeId, reason }, }); await notifyDelegate(delegateToId, taskId); } Тайм-аути перевіряються кроном щогодини. Якщо завдання прострочене — надсилається сповіщення погоджувачу та ескалація керівнику. Можна налаштувати автоматичне схвалення при простроченні.
// Cron job: перевіряємо прострочені завдання щогодини async function processOverdueTasks() { const overdueTasks = await db.workflowTasks.findAll({ status: 'pending', dueAt: { lt: new Date() }, escalationSentAt: null, }); for (const task of overdueTasks) { const step = getStepConfig(task); if (step.escalationUserId) { // Сповіщаємо керівника await notifyEscalation(step.escalationUserId, task); await db.workflowTasks.update(task.id, { escalationSentAt: new Date() }); } if (step.autoApproveOnTimeout) { await workflowEngine.processDecision(task.id, 'approve', 'Auto-approved on timeout', 'system'); } } } Візуалізація прогресу
Ініціатор бачить timeline workflow: який крок виконано, хто погодив, хто ще не відповів, скільки часу чекаємо. React-компонент з вертикальним списком, іконками статусів (✓, ✗, ⏳) та tooltip'ами з коментарями.
Сповіщення
| Подія | Кому | Терміновість |
|---|---|---|
| Завдання призначено | Погоджувач | Негайно |
| Дедлайн через 4 год | Погоджувач | Push + Email |
| Прострочено завдання | Погоджувач + ескалація | |
| Документ схвалено | Ініціатор | In-app + Email |
| Документ відхилено | Ініціатор | Негайно, всі канали |
Чому варто впровадити workflow на сайті?
Workflow на нашому движку в 3 рази швидший за паперовий документообіг і на 50% ефективніший за прості email-сповіщення. Ви отримуєте прозорість, контроль та економію ресурсів. Типовий проєкт окупається за 3–6 місяців за рахунок скорочення часу співробітників. Середня економія на операційних витратах може досягати значної суми. Ми гарантуємо якість: 5 років досвіду, сертифіковані інженери, 12 місяців підтримки після впровадження.
Що входить в роботу?
- Аналітика: вивчаємо бізнес-процеси, ролі та типи документів.
- Проектування: створюємо схему workflow з кроками, умовами та ролями.
- Реалізація: розробляємо движок, інтеграцію зі сховищем документів та ЕЦП.
- Інтерфейс: особистий кабінет ініціатора та погоджувачів.
- Тестування: покриття юніт-тестами, навантажувальне тестування.
- Документація: опис API, інструкції користувача, адміністрування.
- Навчання: вебінар для ключових користувачів.
- Підтримка: 2 тижні безкоштовної пост-продакшн підтримки.
Терміни орієнтовно
| Комплектація | Термін |
|---|---|
| Базовий workflow (послідовне погодження, завдання, сповіщення) | 7–10 днів |
| Розширений (паралельне, делегування, ескалація, тайм-аути) | 12–17 днів |
| З візуальним конструктором шаблонів | 19–27 днів |
Точні терміни розраховуємо після аудиту ваших процесів. Зв'яжіться з нами — проведемо безкоштовний аудит і запропонуємо рішення за 1 день. Замовте впровадження та скоротите час погоджень у 3 рази. Отримайте консультацію вже сьогодні.







