Чому варто розробити власну PM-систему?
Ми розробляємо системи управління проектами під ключ, коли готові SaaS-продукти не підходять: галузева специфіка, жорсткі вимоги до даних, інтеграція з внутрішніми системами. Замість Jira або Asana ви отримуєте інструмент, заточений під ваш бізнес-процес. Нижче — архітектура, кодова база та терміни. Замовте оцінку проекту, щоб зрозуміти деталі. За 10+ років ми реалізували понад 50 проектів — від модульних монолітів до розподілених систем.
Власна PM-система вирішує три головні проблеми: нестандартні воркфлоу, які не можна переналаштувати в готовому продукті; висока вартість ліцензій при масштабуванні; необхідність глибокої інтеграції з корпоративним стеком. За нашими даними, економія на ліцензіях при 500+ користувачах досягає 60%, а скорочення часу на воркфлоу — 40%. Кастомна PM-система окупається в середньому за 12-18 місяців. Зв'яжіться з нами, щоб отримати консультацію.
Порівняння: кастомна PM-система vs Jira
| Параметр | Кастомна PM-система | Jira (SaaS) |
|---|---|---|
| Вартість при 500+ користувачах | До 60% дешевше | Висока річна підписка |
| Гнучкість воркфлоу | Будь-які переходи, guards, візуальний редактор | Тільки стандартні схеми, складні кастомізації дорогі |
| Інтеграції | Будь-які системи через API, OAuth, webhooks | Обмежений набір, додаткові плагіни |
| Дані | Повний контроль, зберігання у вас | На серверах вендора, експорт обмежений |
| Продуктивність | Налаштовувана, до 10 000 одночасних користувачів | Залежить від тарифу, можливі ліміти |
Архітектура та модель даних
Центральні сутності: Project → Milestone → Task → Subtask. Поперечні: User, Team, Comment, Attachment, TimeLog, Activity. Зв'язки: задача може належати кільком проектам через епіки, користувач — різні ролі, залежності між задачами утворюють граф.
Модульний моноліт — правильний вибір для проектів до 50 000 активних користувачів. Мікросервіси виправдані, коли окремі компоненти масштабуються незалежно. 90% систем PM будуються як модульний моноліт і залишаються ним назавжди.
Event-driven всередині моноліту. Переходи станів, призначення, зміни дедлайнів — все це події, що тригерять побічні ефекти (сповіщення, дашборди, логи). Використовуємо внутрішній event bus: в Laravel Event::dispatch(), в Node.js — EventEmitter.
CREATE TABLE tasks (
id BIGSERIAL PRIMARY KEY,
project_id BIGINT NOT NULL REFERENCES projects(id),
parent_id BIGINT REFERENCES tasks(id),
path LTREE NOT NULL, -- PostgreSQL ltree: '1.5.23'
title VARCHAR(500) NOT NULL,
status task_status NOT NULL DEFAULT 'todo',
priority SMALLINT NOT NULL DEFAULT 2,
assignee_id BIGINT REFERENCES users(id),
due_date DATE,
estimate INTEGER, -- в хвилинах
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX tasks_path_gist ON tasks USING GIST (path);
CREATE INDEX tasks_project_status ON tasks (project_id, status);
Цей підхід з ltree описаний в документації PostgreSQL.
Залежності між задачами:
CREATE TABLE task_dependencies (
task_id BIGINT REFERENCES tasks(id),
depends_on_id BIGINT REFERENCES tasks(id),
type dep_type NOT NULL,
PRIMARY KEY (task_id, depends_on_id)
);
Перед збереженням залежності перевіряємо циклічність — обхід графа в глибину або рекурсивний CTE.
Як реалізувати воркфлоу та реалтайм?
Воркфлоу — головна причина розробки власної системи. Підхід: налаштовувані воркфлоу на рівні типу задачі. Кожен тип (Task, Bug, Epic) має власну state machine з різними переходами та guards.
// Laravel + winzou/state-machine
'bug' => [
'graph' => 'bug_workflow',
'property_path' => 'status',
'states' => ['new', 'triaged', 'in_progress', 'in_review', 'resolved', 'closed', 'reopened'],
'transitions' => [
'triage' => ['from' => ['new'], 'to' => 'triaged'],
'start' => ['from' => ['triaged'], 'to' => 'in_progress'],
'review' => ['from' => ['in_progress'], 'to' => 'in_review'],
'resolve' => ['from' => ['in_review'], 'to' => 'resolved'],
'close' => ['from' => ['resolved'], 'to' => 'closed'],
'reopen' => ['from' => ['resolved', 'closed'], 'to' => 'reopened'],
],
'callbacks' => [
'after' => [
'notify_assignee' => ['on' => ['start', 'review'], 'do' => 'NotifyAssigneeCallback'],
],
],
],
Конфігурація воркфлоу зберігається в базі, редагується через візуальний конструктор.
Покрокове налаштування state machine
- Визначте стани та переходи для кожного типу задачі.
- Створіть guards для перевірки прав та умов.
- Зареєструйте callbacks для сповіщень та аудиту.
- Протестуйте всі переходи через unit-тести.
Реалтайм-оновлення. Стек: Laravel Reverb, Soketi або Ably. Приватні канали на рівні проекту та задачі. Presence-канали показують, хто переглядає задачу. Оптимістичні оновлення на фронті через React Query.
// Frontend: Laravel Echo + React
const channel = window.Echo.private(`project.${projectId}`);
channel
.listen('.task.updated', (e) => {
queryClient.invalidateQueries(['tasks', e.task.id]);
})
.listen('.comment.created', (e) => {
setComments(prev => [...prev, e.comment]);
});
Які представлення та тайм-трекінг потрібні?
Мінімальний набір: Kanban-дошка (drag-and-drop через @dnd-kit/core, віртуалізація при 50+ картках), список з вкладеністю (tree-table, серверне сортування), діаграма Ганта (frappe-gantt або @dhtmlx/gantt, відображення залежностей), календарний вигляд (FullCalendar).
Тайм-трекінг. Глобальний таймер в UI, зберігає стан в localStorage, синхронізує з сервером. Дані логів зберігаються в таблиці з автоматично обчислюваним duration. При закритті вкладки — beforeunload зберігає поточний інтервал.
Як реалізувати ролі, сповіщення та пошук?
RBAC з project-scope ролями. System roles (admin, member) та project roles (owner, manager, developer, viewer, external). Використовуємо spatie/laravel-permission з прив'язкою до моделі Project. Гостьовий доступ через окремі токени.
Сповіщення — багатоканальні: email, push, in-app, Slack. Користувач налаштовує підписки в профілі. Технічно: черга через Laravel Queues / BullMQ, батчинг email-листів.
Пошук. PostgreSQL FTS через tsvector достатній до 200 000 задач. Для більшого обсягу — OpenSearch.
ALTER TABLE tasks ADD COLUMN search_vector TSVECTOR;
UPDATE tasks SET search_vector =
to_tsvector('ukrainian', coalesce(title, '') || ' ' || coalesce(description, ''));
CREATE INDEX tasks_search ON tasks USING GIN(search_vector);
Як забезпечити продуктивність PM-системи?
Проблема N+1 та її вирішення
N+1 query на списку задач вирішується eager loading. Денормалізація лічильників прогресу. Cursor-based пагінація для великих списків.
Інтеграції з Git-репозиторіями, CI/CD, Slack/Teams, Confluence/Notion, Google Calendar будуються на OAuth 2.0, webhooks та REST API. Токени шифруються.
Що входить в роботу
Після завершення проекту ви отримуєте:
- Повний вихідний код системи з коментарями
- Документацію з архітектури, моделі даних, API
- Docker-конфігурації для розгортання
- Інструкції з експлуатації та резервного копіювання
- Навчання команди (до 3 сесій)
- Гарантійна підтримка 3 місяці
Орієнтовні терміни
| Етап | Зміст | Тривалість |
|---|---|---|
| Проектування | Воркфлоу, ролі, інтеграції, wireframes | 3–4 тиж. |
| Ядро системи | Проекти, задачі, воркфлоу, права | 6–8 тиж. |
| UI: список + Kanban | Базові представлення | 4–5 тиж. |
| Реалтайм + сповіщення | WebSocket, email, push | 2–3 тиж. |
| Gantt + календар | Складні представлення | 3–4 тиж. |
| Тайм-трекінг | Таймер, логи, звіти | 2 тиж. |
| Інтеграції (2–3 шт.) | Git + Slack + Calendar | 3–4 тиж. |
| Тестування, запуск | E2E, навантажувальне | 2–3 тиж. |
Повний проект: 22–32 тижні. Ітераційний запуск через 10–12 тижнів — core-функціонал без Gantt та інтеграцій. Замовте оцінку проекту і отримайте оптимальний план.
Як ми гарантуємо якість
Наш досвід — 10+ років у розробці корпоративних систем. Кожен проект проходить рев'ю архітектури, навантажувальне тестування та аудит безпеки перед запуском. Гарантуємо стабільну роботу під навантаженням до 10 000 одночасних користувачів. Зв'яжіться з нами для отримання консультації. Отримайте розрахунок вартості вашого проекту.







