Please use this identifier to cite or link to this item: https://er.chdtu.edu.ua/handle/ChSTU/9755
Title: Розробка програмної системи автоматизації HR-процесів підприємства
Authors: Салапатов, Володимир Іванович
Курильчук, Максим Миколайович
Keywords: автоматизація HR-процесів;штучний інтелект;великі мовні моделі;OPENROUTER API;PROMPT ENGINEERING;парсинг резюме;DJANGO REST FRAMEWORK;REACT;TYPESCRIPT;POSTGRESQL;JWT;KANBAN;HR process automation;artificial intelligence;large language models;OPENROUTER API;PROMPT ENGINEERING;CV parsing;DJANGO REST FRAMEWORK;REACT;TYPESCRIPT;POSTGRESQL;JWT;KANBAN
Issue Date: 17-Jun-2026
Abstract: АНОТАЦІЯ Кваліфікаційна робота бакалавра Курильчука М.М. на тему «Розробка програмної системи автоматизації HR-процесів підприємства» за спеціальністю 121 «Інженерія програмного забезпечення». ЧДТУ, Черкаси, 2026. Робота містить 101 сторінку, 27 таблиць, 58 рисунків, 46 джерел, 4 додатки. Кваліфікаційну роботу присвячено розробці повнофункціональної веб-системи для автоматизації основних HR-процесів підприємства із застосуванням технологій штучного інтелекту. Система охоплює чотири ключові функціональні підсистеми: управління організаційною структурою та кадровим складом, автоматизований облік відпусток із перерахунком балансу, рекрутинг з Kanban-дошкою [52], а також інтелектуальний модуль аналізу резюме на базі великих мовних моделей (LLM). Принциповою інноваційною складовою є AI-модуль, реалізований у файлі recruitment/cv_parsing.py, що інтегрує LLM через уніфікований шлюз OpenRouter API. Модуль забезпечує автоматичне виокремлення структурованих відомостей з PDF-документів шляхом prompt engineering, повертаючи дані у форматі JSON без потреби у попередньому навчанні. Передбачено механізм автоматичного добору безкоштовних моделей та алгоритм повторних спроб із зростаючою затримкою (exponential backoff) при перевищенні ліміту запитів. Серверну частину реалізовано на Python 3.11 / Django 6.0.5 / Django REST Framework 3.16.1 із JWT-автентифікацією (SimpleJWT) та рольовою моделлю розмежування доступу (3 ролі, 4 Permission-класи). Клієнтський застосунок розроблено як SPA на React 19 + TypeScript 6.0 із власним pub/sub-стором стану автентифікації. Зберігання даних реалізовано у PostgreSQL з перевірними обмеженнями цілісності на рівні СУБД. Об'єкт розробки: процес автоматизації управління людськими ресурсами підприємства засобами програмного забезпечення. Предмет розробки: програмна система автоматизації HR-процесів підприємства з інтегрованим AI-модулем інтелектуального парсингу резюме кандидатів на основі великих мовних моделей. Практичний ефект впровадження: автоматизований AI-парсинг скорочує час опрацювання одного резюме з 15–20 хвилин ручної роботи до 3–5 секунд, що забезпечує підвищення продуктивності HR-відділу на 85–90% при нульових витратах на AI-обробку завдяки безкоштовним моделям OpenRouter.
ANNOTATION Bachelor's thesis by M. M. Kurylchuk on the topic "Development of a Software System for Automation of Enterprise HR Processes" in the specialty 121 "Software Engineering". ChSTU, Cherkasy, 2026. The thesis contains 101 pages, 27 tables, 58 figures, 46 references, and 4 appendices. The thesis is devoted to the development of a fully functional web system for automating the core HR processes of an enterprise using artificial intelligence technologies. The system encompasses four key functional subsystems: organizational structure and personnel management; automated leave accounting with balance recalculation; recruitment management with a Kanban board; and an intelligent resume analysis module based on large language models (LLMs). A fundamental innovative component is the AI module implemented in the recruitment/cv_parsing.py file, which integrates LLMs through the unified OpenRouter API gateway. The module ensures the automatic extraction of structured information from PDF documents via prompt engineering, returning data in JSON format without the need for fine-tuning. It incorporates a mechanism for the automatic selection of free models and a retry algorithm with exponential backoff when request rate limits are exceeded. The backend is implemented using Python 3.11 / Django 6.0.5 / Django REST Framework 3.16.1 with JWT authentication (SimpleJWT) and a role-based access control (RBAC) model (3 roles, 4 permission classes). The client application is developed as a Single Page Application (SPA) on React 19 + TypeScript 6.0 with a custom pub/sub authentication state store. Data storage is implemented in PostgreSQL with integrity check constraints on the database level. Object of development: the process of automating enterprise human resource management using software tools. Subject of development: a software system for automating enterprise HR processes with an integrated AI module for the intelligent parsing of candidate resumes based on large language models. Practical implementation effect: automated AI parsing reduces the processing time for a single resume from 15–20 minutes of manual work to 3–5 seconds. This provides an 85–90% increase in the HR department's productivity with zero AI processing costs, achieved through the use of free OpenRouter models.
URI: https://er.chdtu.edu.ua/handle/ChSTU/9755
Appears in Collections:121 Інженерія програмного забезпечення (Інженерія програмного забезпечення)



Items in DSpace are protected by copyright, with all rights reserved, unless otherwise indicated.

Extracted text
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ 
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ 
Факультет інформаційних технологій і систем 
Кафедра програмного забезпечення автоматизованих систем 
ПОЯСНЮВАЛЬНА ЗАПИСКА 
до кваліфікаційної роботи  
бакалавра 
На тему: «Розробка програмної системи автоматизації HR-процесів підприємства» 
Виконав: студент 4 курсу, групи ПЗ-2204 
спеціальності  
121 «Інженерія програмного забезпечення» 
(шифр і назва напряму підготовки) 
Студент Курильчук М.М 
(прізвище та ініціали) 
Керівник Салапатов В.І 
(прізвище та ініціали) 
Рецензент  Сметанін О.Г. 
(прізвище та ініціали) 
Черкаси 2026 
Черкаський державний технологічний університет 
повне найменування вищого навчального закладу 
Факультет інформаційних технологій і систем  
Кафедра  програмного забезпечення автоматизованих систем  
Освітній рівень  бакалавр  
Спеціальність 121 «Інженерія програмного забезпечення»  
Освітня програма Інженерія програмного забезпечення  
 
 
ЗАТВЕРДЖУЮ 
Зав. кафедри ПЗАС, професор 
____________________ С. Голуб  
«___» _______________ 2026 року 
 
ЗАВДАННЯ 
НА КВАЛІФІКАЦІЙНУ РОБОТУ СТУДЕНТУ 
Курильчук Максим Миколайович 
(прізвище, ім’я, по батькові) 
1. Тему проекту (роботи) Розробка програмної системи автоматизації HR-процесів підприємства 
Керівник проекту (роботи) Салапатов В.І. к.т.н. ,доцент  
(прізвище, ім’я , по батькові, науковий ступінь, вчене звання) 
Затверджені наказом Черкаського державного технологічного університету від « 12 » березня 
2026 року №56/03-03 
2. Строк подання студентом проекту (роботи)   
3. Вхідні дані до проекту (роботи) вимоги до автоматизації кадрового обліку, управління 
відпустками та рекрутингу; методи інтеграції великих мовних моделей (LLM) через OpenRouter 
API для інтелектуального парсингу PDF-резюме  
4. Зміст розрахунково-пояснювальної записки: Вступ; Розділ 1. Аналіз предметної галузі та огляд 
існуючих рішень; Розділ 2. Проектування системи з використанням UML; Розділ 3. Розробка та 
тестування програмного комплексу; Висновки; Список використаних джерел; Додатки. 
5. Перелік графічного матеріалу: діаграми UML (прецедентів, класів, компонентів, розгортання, 
послідовності, діяльності, скінченного автомату); схеми архітектури системи та бази даних. 
  
 
 
6. Консультанти розділів роботи
Прізвище, ініціали та посади Підпис, дата 
Розділ 
консультанта Завдання видав Завдання прийняв 
1 
2 
3 
7. Дата видачі завдання 16 січня 2026 р.
КАЛЕНДАРНИЙ ПЛАН 
Строк 
виконання 
№ 
Назва етапів випускної роботи етапів Примітки 
п/п 
кваліфікаційної
роботи 
1 Підбір матеріалів 14.11.2025 виконано 
2 Аналіз шляхів вирішення поставленої задачі 28.11.2025 виконано 
3 Розрахунок основних параметрів роботи 19.12.2025 виконано 
4 Вибір кінцевого варіанту проектного рішення 30.01.2026 виконано 
5 Оформлення первісної редакції роботи 06.03.2026 виконано 
Заключна стадія 
1 Узгодження прийнятих проектних рішень з 15.04.2026 виконано 
керівником 
2 Оформлення пояснювальної записки роботи в 19.05.2026 виконано 
кінцевій редакції 
3 Попередній захист роботи 22.05.2026 виконано 
4 Затвердження роботи 25.05.2026 виконано 
5 Рецензування роботи 29.05.2026 виконано 
6 Захист роботи 09.06.2026
Студент _____________________ Курильчук М.М. 
(підпис) (прізвище та ініціали) 
Керівник роботи _____________________ Салапатов В.І. 
(підпис) (прізвище та ініціали)
АНОТАЦІЯ 
Кваліфікаційна робота бакалавра Курильчука М.М. на тему «Розробка 
програмної системи автоматизації HR-процесів підприємства» за спеціальністю 
121 «Інженерія програмного забезпечення». ЧДТУ, Черкаси, 2026. 
Робота містить 101 сторінку, 27 таблиць, 58 рисунків, 46 джерел, 4 додатки.
 Кваліфікаційну роботу присвячено розробці повнофункціональної веб-
системи для автоматизації основних HR-процесів підприємства із застосуванням 
технологій штучного інтелекту. Система охоплює чотири ключові функціональні 
підсистеми: управління організаційною структурою та кадровим складом, 
автоматизований облік відпусток із перерахунком балансу, рекрутинг з Kanban-
дошкою [52], а також інтелектуальний модуль аналізу резюме на базі великих 
мовних моделей (LLM). 
Принциповою інноваційною складовою є AI-модуль, реалізований у файлі 
recruitment/cv_parsing.py, що інтегрує LLM через уніфікований шлюз OpenRouter 
API. Модуль забезпечує автоматичне виокремлення структурованих відомостей з 
PDF-документів шляхом prompt engineering, повертаючи дані у форматі JSON без 
потреби у попередньому навчанні. Передбачено механізм автоматичного добору 
безкоштовних моделей та алгоритм повторних спроб із зростаючою затримкою 
(exponential backoff) при перевищенні ліміту запитів. 
Серверну частину реалізовано на Python 3.11 / Django 6.0.5 / Django REST 
Framework 3.16.1 із JWT-автентифікацією (SimpleJWT) та рольовою моделлю 
розмежування доступу (3 ролі, 4 Permission-класи). Клієнтський застосунок 
розроблено як SPA на React 19 + TypeScript 6.0 із власним pub/sub-стором стану 
автентифікації. Зберігання даних реалізовано у PostgreSQL з перевірними 
обмеженнями цілісності на рівні СУБД. 
Об'єкт розробки: процес автоматизації управління людськими ресурсами 
підприємства засобами програмного забезпечення. 
Предмет розробки: програмна система автоматизації HR-процесів 
підприємства з інтегрованим AI-модулем інтелектуального парсингу резюме 
кандидатів на основі великих мовних моделей. 
 
 
Практичний ефект впровадження: автоматизований AI-парсинг скорочує час 
опрацювання одного резюме з 15–20 хвилин ручної роботи до 3–5 секунд, що 
забезпечує підвищення продуктивності HR-відділу на 85–90% при нульових 
витратах на AI-обробку завдяки безкоштовним моделям OpenRouter. 
КЛЮЧОВІ СЛОВА: автоматизація HR-процесів, штучний інтелект, великі 
мовні моделі, OPENROUTER API, PROMPT ENGINEERING, парсинг резюме, 
DJANGO REST FRAMEWORK, REACT, TYPESCRIPT, POSTGRESQL, JWT, 
KANBAN. 
  
 
 
ANNOTATION 
Bachelor's thesis by M. M. Kurylchuk on the topic "Development of a Software 
System for Automation of Enterprise HR Processes" in the specialty 121 "Software 
Engineering". ChSTU, Cherkasy, 2026. 
The thesis contains 101 pages, 27 tables, 58 figures, 46 references, and 4 
appendices. 
The thesis is devoted to the development of a fully functional web system for 
automating the core HR processes of an enterprise using artificial intelligence 
technologies. The system encompasses four key functional subsystems: organizational 
structure and personnel management; automated leave accounting with balance 
recalculation; recruitment management with a Kanban board; and an intelligent resume 
analysis module based on large language models (LLMs). 
A fundamental innovative component is the AI module implemented in the 
recruitment/cv_parsing.py file, which integrates LLMs through the unified OpenRouter 
API gateway. The module ensures the automatic extraction of structured information 
from PDF documents via prompt engineering, returning data in JSON format without the 
need for fine-tuning. It incorporates a mechanism for the automatic selection of free 
models and a retry algorithm with exponential backoff when request rate limits are 
exceeded. 
The backend is implemented using Python 3.11 / Django 6.0.5 / Django REST 
Framework 3.16.1 with JWT authentication (SimpleJWT) and a role-based access control 
(RBAC) model (3 roles, 4 permission classes). The client application is developed as a 
Single Page Application (SPA) on React 19 + TypeScript 6.0 with a custom pub/sub 
authentication state store. Data storage is implemented in PostgreSQL with integrity 
check constraints on the database level. 
Object of development: the process of automating enterprise human resource 
management using software tools. 
Subject of development: a software system for automating enterprise HR 
processes with an integrated AI module for the intelligent parsing of candidate resumes 
based on large language models. 
 
 
Practical implementation effect: automated AI parsing reduces the processing 
time for a single resume from 15–20 minutes of manual work to 3–5 seconds. This 
provides an 85–90% increase in the HR department's productivity with zero AI processing 
costs, achieved through the use of free OpenRouter models. 
KEYWORDS: HR process automation, artificial intelligence, large language 
models, OPENROUTER API, PROMPT ENGINEERING, CV parsing, DJANGO REST 
FRAMEWORK, REACT, TYPESCRIPT, POSTGRESQL, JWT, KANBAN
 
 
ЗМІСТ 
ПЕРЕЛІК УМОВНИХ  ПОЗНАЧЕНЬ ...................................................................... 6 
ВСТУП ............................................................................................................................. 8 
РОЗДІЛ 1. ІСНУЮЧІ МЕТОДИ ТА ЗАСОБИ РОЗВ'ЯЗАННЯ 
ПОСТАВЛЕНИХ ЗАВДАНЬ ..................................................................................... 12 
1.1. Аналіз предметної галузі HR-процесів ............................................................ 12 
1.2. Огляд існуючих HR-систем та їх порівняльний аналіз .................................. 12 
1.2.1. Workday Human Capital Management ......................................................... 13 
1.2.2. BambooHR .................................................................................................... 14 
1.2.3. SAP SuccessFactors ...................................................................................... 15 
1.2.4. Порівняльний аналіз систем ....................................................................... 16 
1.3. Аналіз методів застосування штучного інтелекту у HR ................................ 17 
1.3.1. Традиційні NLP-методи аналізу резюме .................................................. 17 
1.3.2. Великі мовні моделі для парсингу резюме ............................................... 17 
1.3.3. OpenRouter як уніфікований шлюз до LLM ............................................. 18 
1.3.4. Витяг тексту з PDF-документів ................................................................. 19 
1.4. Обґрунтування вибору технологічного стеку ................................................. 19 
1.4.1. Python та Django REST Framework ............................................................ 19 
1.4.2. React 19 та TypeScript ................................................................................. 19 
1.4.3. PostgreSQL ................................................................................................... 19 
РОЗДІЛ 2. ВПРОВАДЖЕННЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ У ПРАКТИКУ 
ПРОЄКТУВАННЯ ПРОГРАМНОГО ЗАБЕЗПЕЧЕННЯ ІНФОРМАЦІЙНИХ 
СИСТЕМ ....................................................................................................................... 21 
2.1. Моделювання предметної області .................................................................... 21 
2.1.1. Предметна область моделювання. Модель предметної області. Словник 
предметної області ................................................................................................ 21 
2.1.2. Елементи моделювання предметної області ............................................ 23 
2.1.3. Робоча область моделювання .................................................................... 24 
2.2. Формування та аналіз вимог ............................................................................. 25
ЧДТУ 26 2247. 008 ПЗ
. 
Змн. Арк. № докум. Підпис Дата 
Розроб. Курильчук М.М. Літ. Лист Листів 
Перевір Салапатов В.І. Розробка програмної системи 4 
автоматизації HR-процесів 
Н. Конт. Півень О.Б. підприємства ФІТІС, кафедра ПЗАС, ПЗ-2204 
Затверд. Голуб С.В. 
2.2.1. Формування вимог до програмного забезпечення. Первинні і детальні 
вимоги. Вимоги замовника і розробника. Функціональні та нефункціональні 
вимоги ..................................................................................................................... 25 
2.2.2. Формування вимог за допомогою діаграми прецедентів ........................ 30 
2.3. Проектування логічної структури програмного комплексу .......................... 33 
2.3.1. Діаграми класів ............................................................................................ 34 
2.3.2. Діаграма пакетів .......................................................................................... 44 
2.4. Архітектурне проектування .............................................................................. 45 
2.4.1. Діаграма компонентів ................................................................................. 45 
2.4.2. Розгортання програмної системи на апаратних засобах. Діаграма 
розгортання ............................................................................................................ 46 
2.5. Моделювання поведінки системи ..................................................................... 47 
2.5.1. Діаграма діяльності ..................................................................................... 47 
2.5.2. Діаграма послідовності ............................................................................... 55 
2.5.3. Діаграма комунікації ................................................................................... 57 
2.5.4. Діаграма скінченного автомата ................................................................. 58 
РОЗДІЛ 3. РОЗРОБКА ТА ТЕСТУВАННЯ ПРОГРАМНОГО 
ЗАБЕЗПЕЧЕННЯ ........................................................................................................ 62 
3.1. Розробка програмного комплексу .................................................................... 62 
3.1.1. Обґрунтування вибору засобів реалізації ................................................. 62 
3.1.2. Опис структурної (функціональної) схеми. ............................................. 63 
3.1.3. Опис логічної схеми системи ..................................................................... 85 
3.1.4. Розробка бази даних. ................................................................................... 89 
3.1.5. Розробка інтерфейсу користувача ............................................................. 94 
3.1.6. Опис розробки програмних компонентів ................................................. 97 
3.2. Тестування системи ......................................................................................... 114 
3.2.1. Модульне тестування ................................................................................ 114 
3.2.2. Інтеграційне тестування ........................................................................... 118 
3.2.3. Системне тестування ................................................................................ 120 
3.2.4. Приймальне тестування ............................................................................ 121 
3.3. Приклади впровадженого програмного комплексу ...................................... 122 
ВИСНОВКИ ............................................................................................................... 125 
ЧДТУ 26. 2247.008 ПЗ
Змн. Арк. № докум Підпис Дата 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ .............................................................. 128 
ДОДАТОК А ............................................................................................................... 133 
ДОДАТОК Б ............................................................................................................... 135 
ДОДАТОК В ............................................................................................................... 151 
ДОДАТОК Г ............................................................................................................... 159 
ЧДТУ 262247.008 ПЗ
Змн. Арк. № докум Підпис Дата 
ЧДТУ 262247.008 ПЗ 
ПЕРЕЛІК УМОВНИХ  ПОЗНАЧЕНЬ 
AI / ШІ Artificial Intelligence — штучний інтелект 
API Application Programming Interface — програмний інтерфейс 
застосунку 
ATS Applicant Tracking System — система відстеження кандидатів 
CORS Cross-Origin Resource Sharing — спільне використання 
ресурсів між джерелами 
CRUD Create, Read, Update, Delete — базові операції з даними 
CV Curriculum Vitae — резюме 
DRF Django REST Framework — фреймворк для побудови REST 
API на Django 
FK Foreign Key — зовнішній ключ 
HR Human Resources — управління людськими ресурсами 
HTTP HyperText Transfer Protocol — протокол передачі 
гіпертекстових документів 
JSON JavaScript Object Notation — легкий формат обміну даними 
JWT JSON Web Token — токен для безпечної передачі даних між 
сторонами 
LLM Large Language Model — велика мовна модель 
NER Named Entity Recognition — розпізнавання іменованих 
сутностей 
NLP Natural Language Processing — обробка природної мови 
ORM Object-Relational Mapping — об'єктно-реляційне 
відображення 
PDF Portable Document Format — формат електронних документів 
6 
ЧДТУ 262247.008 ПЗ 
PK Primary Key — первинний ключ 
REST Representational State Transfer — архітектурний стиль 
побудови API 
SPA Single Page Application — односторінковий застосунок 
SQL Structured Query Language — мова структурованих запитів 
до БД 
UI User Interface — користувацький інтерфейс 
UML Unified Modeling Language — уніфікована мова 
моделювання 
БД База даних 
КРБ Кваліфікаційна робота бакалавра 
ПЗ Програмне забезпечення 
СУБД Система управління базами даних 
7 
ЧДТУ 262247.008 ПЗ 
ВСТУП 
Актуальність теми. Дана кваліфікаційна робота бакалавра належить до 
спеціальності «Інженерія програмного забезпечення». Управління людськими 
ресурсами (Human Resources Management, HRM) є одним із ключових бізнес-
процесів сучасного підприємства. З погляду інженерії програмного забезпечення, 
розв'язання цієї проблеми полягає у створенні спеціалізованої програмної системи, 
яка охоплює повний цикл розробки: від аналізу вимог і проектування архітектури 
до реалізації, тестування та розгортання готового продукту. Застосування клієнт-
серверної архітектури, REST API, реляційних баз даних і сучасних веб-
фреймворків є усталеними практиками галузі, що забезпечують масштабованість і 
зручність супроводу системи. Додатковим інженерним викликом є інтеграція AI-
модуля для автоматизованого аналізу резюме, що потребує проектування надійних 
інтерфейсів взаємодії із зовнішніми мовними моделями та обробки 
неструктурованих текстових даних. 
Таким чином, розробка програмної системи автоматизації HR-процесів є 
актуальною як з практичної точки зору бізнесу, так і з позиції демонстрації 
ключових компетентностей спеціальності «Інженерія програмного забезпечення». 
Стрімкий розвиток технологій штучного інтелекту, зокрема великих мовних 
моделей (Large Language Models, LLM), відкрив принципово нові можливості для 
інтелектуальної автоматизації роботи з неструктурованими текстовими 
документами. Сучасні LLM — GPT-4o [33], Claude 3.5 Sonnet [48], Mistral Large 
[56] та їх відкриті аналоги [47] — здатні аналізувати довільно структуровані 
резюме кандидатів і виокремлювати структуровану інформацію без необхідності 
попереднього навчання під конкретні шаблони документів [2]. 
Попри наявність комерційних HR-платформ (Workday [6], BambooHR [7], SAP 
SuccessFactors [8]), вони мають суттєві обмеження для підприємств малого та 
середнього бізнесу: надмірно висока вартість ліцензій, тривалість впровадження та 
відсутність локалізації для українського ринку. Розробка спеціалізованої системи, 
8 
ЧДТУ 26247.008 ПЗ 
адаптованої до реальних потреб підприємства з вбудованим AI-модулем та 
підтримкою державної мови, є актуальним і практично значущим завданням [3]. 
Мета і завдання розробки. Метою кваліфікаційної роботи є проектування 
та розробка програмного забезпечення веб-системи автоматизації HR-процесів 
підприємства із вбудованим модулем інтелектуального аналізу резюме кандидатів 
на базі великих мовних моделей засобами сучасної інженерії програмного 
забезпечення. 
Для досягнення поставленої мети необхідно вирішити такі завдання: — 
провести аналіз предметної галузі HR-процесів та виконати огляд існуючих систем 
автоматизації [22]; — дослідити методи застосування штучного інтелекту у сфері 
управління персоналом [19][20 ]; — спроектувати архітектуру клієнт-серверної 
системи та структуру реляційної бази даних [36][37]; — розробити серверну 
частину на базі Python [58] / Django REST Framework [14] з JWT-автентифікацією 
[29][49] та рольовим розмежуванням доступу; — реалізувати AI-модуль 
автоматичного парсингу PDF-резюме [13] через OpenRouter API [12] з підтримкою 
LLM та regex-резерву; — розробити клієнтську частину як SPA на React 19 [15] + 
TypeScript [30 ] з модулями управління персоналом, відпустками та рекрутингом 
[52]; — провести багаторівневе тестування розробленої системи [39][50 ][51] та 
оцінити ефективність AI-модуля. 
Об'єкт розробки. Об'єктом розробки є програмне забезпечення для 
автоматизації процесів управління персоналом підприємства, а саме: ведення 
кадрового обліку співробітників, управління відпустками та рекрутингова 
діяльність, що включає обробку й аналіз резюме кандидатів. Зазначені процеси 
виступають предметом програмної автоматизації в рамках розроблюваної системи. 
Предмет розробки. Предметом розробки є методи та засоби інженерії 
програмного забезпечення для автоматизації HR-процесів підприємства із 
застосуванням сучасних веб-технологій та інструментів штучного інтелекту на базі 
великих мовних моделей (LLM) [2][19] — для інтелектуального аналізу PDF-
документів [13] та витягу структурованих даних. 
9 
ЧДТУ 262247.008 ПЗ 
Методи проектування та конструювання. Для досягнення поставленої 
мети в роботі застосовано такі методи та підходи інженерії програмного 
забезпечення. Об'єктно-орієнтований аналіз і проектування використовувались при 
побудові архітектури системи та проектуванні бази даних [25, 27]. UML-
моделювання застосовувалось для побудови діаграм класів, прецедентів, 
послідовності, компонентів та розгортання [35]. REST-архітектура слугувала 
основою при проектуванні програмного інтерфейсу взаємодії компонентів системи 
[24], а JWT-автентифікація — при програмній реалізації механізмів безпеки [29, 
49]. Технологія prompt engineering застосовувалась при налаштуванні запитів до 
великих мовних моделей для парсингу резюме [11]. Методи модульного та 
інтеграційного тестування використовувались при верифікації розроблених 
програмних компонентів [17, 18]. 
Опис отриманих результатів. За результатами виконання кваліфікаційної 
роботи розроблено повнофункціональне програмне забезпечення веб-системи 
автоматизації HR-процесів підприємства. Реалізовано модуль управління 
персоналом та організаційною структурою, що охоплює відділи, посади, профілі 
співробітників і трудову діяльність, а також модуль управління відпустками з 
автоматичним підрахунком балансу та журналом затверджень. Розроблено Kanban-
дошку рекрутингу з сімома стадіями опрацювання кандидатів [52] та AI-модуль 
інтелектуального парсингу резюме на основі великих мовних моделей через 
OpenRouter API [2, 12]. Програмно реалізовано систему JWT-автентифікації з 
рольовим розмежуванням доступу [29, 49] та модуль аудиту критичних операцій. 
Зберігання персональних даних співробітників реалізовано відповідно до вимог 
чинного законодавства [59]. 
Практичне значення отриманих результатів. Розроблене програмне 
забезпечення може бути впроваджене на підприємствах малого та середнього 
бізнесу як готове рішення для автоматизації HR-процесів [38, 42]. Застосування AI-
модуля парсингу резюме скорочує час програмної обробки одного документа з 15–
20  хвилин ручної роботи до 3–5 секунд, що забезпечує підвищення продуктивності 
10 
ЧДТУ 262247.008 ПЗ 
HR-відділу на 85–90 %. Використання безкоштовних мовних моделей через 
OpenRouter API [12] дозволяє звести вартість AI-компоненту системи до нуля. 
Особистий внесок автора. Автором особисто виконано повний цикл 
розробки програмного забезпечення: проведено аналіз предметної галузі та 
наявних рішень, спроектовано архітектуру системи і структуру бази даних, 
розроблено серверну частину із застосунками accounts, employees, leaves та 
recruitment, реалізовано AI-модуль cv_parsing.py з інтеграцією OpenRouter API [12], 
розроблено клієнтську частину на основі React 19 [15] і TypeScript [30 ] з 
реалізацією pub/sub authStore [25, 27] та apiClient, а також проведено тестування 
програмних компонентів системи на всіх рівнях [39, 54]. 
11 
ЧДТУ 262247.008 ПЗ 
РОЗДІЛ 1. ІСНУЮЧІ МЕТОДИ ТА ЗАСОБИ РОЗВ'ЯЗАННЯ 
ПОСТАВЛЕНИХ ЗАВДАНЬ 
1.1. Аналіз предметної галузі HR-процесів 
Управління людськими ресурсами (HRM) охоплює весь життєвий цикл 
співробітника — від рекрутингу до звільнення. В рамках даної роботи виокремлено 
чотири основні HR-процеси, автоматизація яких є предметом дослідження [4]: 
– рекрутинг — комплекс заходів із пошуку, відбору та найму нових
співробітників: публікація вакансій, збір та аналіз резюме, проведення
скринінгу, організація співбесід, прийняття рішення щодо найму та
автоматичне формування профілю нового працівника;
– управління персоналом — ведення кадрового обліку підприємства:
профілі співробітників з особистими та контактними даними,
організаційна структура у вигляді відділів і посад, журнал трудової
діяльності;
– управління відпустками — автоматизована обробка заявок на відпустку,
контроль залишку відпускних днів за типами та роками, затвердження або
відхилення заявок уповноваженими особами.
– аудит та звітність — протоколювання критичних операцій для
забезпечення прозорості процесів та відповідальності за прийняті
рішення.
За даними McKinsey [3] Global Institute, впровадження автоматизації HR-
процесів дозволяє скоротити адміністративні витрати на 20–40% та підвищити 
задоволеність співробітників завдяки прозорості та швидкості обробки запитів [3]. 
Найбільший ефект досягається при автоматизації рекрутингу, де опрацювання 
великих обсягів резюме є найбільш ресурсомісткою задачею. 
1.2. Огляд існуючих HR-систем та їх порівняльний аналіз 
Перед початком проектування системи виконано аналіз наявних HR-
платформ з метою виявлення їх переваг і обмежень та врахування отриманих 
12 
ЧДТУ 262247.008 ПЗ 
результатів при проектуванні власного рішення. 
1.2.1. Workday Human Capital Management 
Workday HCM — одна з провідних хмарних платформ для управління 
людськими ресурсами та фінансами [6]. Система надає широкий спектр функцій: 
рекрутинг, управління талантами, розрахунок заробітної плати, аналітику та 
звітність. Використовує алгоритми машинного навчання для рекомендацій 
кандидатів та прогнозування плинності кадрів. 
Рисунок 1.1 – Інтерфейс модуля рекрутингу Workday HCM 
До особливостей Workday HCM відносяться: хмарна архітектура з доступом 
через браузер без встановлення додаткового ПЗ; AI-аналіз відповідності кандидатів 
вимогам вакансій; вбудований розрахунок заробітної плати; розширені аналітичні 
інструменти та звітність [6]. 
Основні переваги: висока функціональність, надійність хмарної 
інфраструктури, придатність для великих підприємств. Суттєві недоліки: вартість 
13 
ЧДТУ 262247.008 ПЗ
від 400000 дол./рік, тривале впровадження (6–18 місяців), відсутність 
україномовного інтерфейсу, орієнтованість виключно на великі корпорації[6].  
1.2.2. BambooHR 
BambooHR — популярна хмарна HR-система, орієнтована на малий та 
середній бізнес [7]. Надає функціонал управління персоналом, відстеження 
робочого часу, управління ефективністю та базовий модуль рекрутингу з ATS. 
Рисунок 1.2 – Головний екран BambooHR 
До особливостей BambooHR відносяться: інтуїтивно зрозумілий інтерфейс 
без складного початкового налаштування; базове управління відпустками; 
14 
ЧДТУ 262247.008 ПЗ 
мобільний застосунок для самообслуговування співробітників. Переваги: відносно 
доступна вартість для МСБ, проста у використанні. Недоліки: відсутність 
інструментів AI для обробки резюме, обмежений функціонал рекрутингу, 
відсутність україномовного інтерфейсу. 
1.2.3. SAP SuccessFactors 
SAP SuccessFactors — корпоративна HR-платформа від SAP, що охоплює 
повний спектр HR-процесів [8]. Включає модулі рекрутингу, навчання і розвитку, 
управління ефективністю та розрахунку зарплати. Використовує AI для аналізу 
резюме та оцінки відповідності кандидатів вимогам вакансій. 
Рисунок 1.3 – Модуль рекрутингу SAP SuccessFactors 
15 
ЧДТУ 262247.008 ПЗ 
Особливості SAP SuccessFactors: AI-скринінг резюме з автоматичною 
оцінкою відповідності; тісна інтеграція з іншими продуктами SAP; повний цикл 
управління талантами від найму до розвитку. Переваги: дуже широкий функціонал, 
глибока AI-інтеграція. Недоліки: вартість впровадження від кількох мільйонів 
доларів, тривале налаштування (12–24 місяці), висока складність для МСБ. 
1.2.4. Порівняльний аналіз систем 
З метою обґрунтування доцільності розробки власного рішення проведено 
порівняльний аналіз розглянутих систем за ключовими критеріями: вартістю 
впровадження, наявністю AI-функціоналу, мовою інтерфейсу, термінами 
розгортання, підтримкою Kanban-рекрутингу, механізмом автентифікації та 
цільовою аудиторією. Результати порівняння наведено в таблиці 1.1. 
Таблиця 1.1 
Порівняльна характеристика HR-систем та розробленої системи 
Критерій Workday BambooHR SAP SF Розроблена система 
Вартість $400k+/рік $6–15/ос/міс $Від 20k/міс Безкоштовно (open 
впровадження source) 
AI-парсинг CV Частково Відсутній Наявний Наявний (LLM + 
regex) 
Мова інтерфейсу Англійська Англійська Кілька мов Українська 
Термін 6–18 міс. 1–3 міс. 12–24 міс. Одразу 
впровадження 
Kanban Наявний Базовий Наявний Наявний (7 стадій) 
рекрутинг 
JWT- Наявна Наявна Наявна Наявна (SimpleJWT) 
автентифікація 
Цільова Великі корп. МСБ Великі корп. МСБ 
аудиторія 
16 
ЧДТУ 262247.008 ПЗ 
З таблиці 1.1 видно, що жодна з розглянутих систем не є оптимальною для 
малого та середнього бізнесу в Україні. Workday та SAP SuccessFactors орієнтовані 
на великі корпорації з відповідними фінансовими можливостями, тоді як 
BambooHR не має AI-функціоналу та підтримки української мови. Зазначені 
обставини обґрунтовують доцільність розробки власного рішення. 
1.3. Аналіз методів застосування штучного інтелекту у HR 
1.3.1. Традиційні NLP-методи аналізу резюме 
До появи великих мовних моделей для автоматизованого аналізу резюме 
використовувались класичні методи обробки природної мови [21]. Регулярні 
вирази (regex) застосовувались для пошуку email-адрес, телефонних номерів, URL-
посилань та стандартизованих дат. Метод Named Entity Recognition (NER) [21] 
дозволяв ідентифікувати власні назви: імена, організації, географічні об'єкти. 
Алгоритми TF-IDF та Word2Vec [44] використовувались для семантичного 
порівняння тексту резюме з описом вакансії. Класифікатори машинного навчання 
забезпечували категоризацію навичок кандидата. 
Зазначені методи мають суттєві обмеження: потребують значного 
передналаштування під конкретний формат резюме, погано справляються з 
варіативністю структури документів та нездатні розуміти контекст. У розробленій 
системі regex-підхід реалізовано як резервний механізм при недоступності AI. 
1.3.2. Великі мовні моделі для парсингу резюме 
Революційним кроком у розвитку AI для HR-сфери стала поява великих 
мовних моделей. Архітектура трансформера, запропонована Vaswani et al. у 2017 
р. [10], стала фундаментом для GPT-4 [33], Claude [48], Mistral [56] та інших 
провідних моделей. LLM демонструють здатність [19] [20] розуміти природну мову 
без спеціального навчання на конкретному форматі документів. 
Ключовою перевагою LLM є можливість застосування техніки prompt 
engineering [11] — формулювання чіткого системного запиту (system prompt), що 
визначає формат вихідних даних у вигляді JSON-схеми. Модель самостійно 
17 
ЧДТУ 262247.008 ПЗ 
виокремлює необхідні відомості з будь-якого резюме: ім'я, email, телефон, роки 
досвіду, навички, поточну посаду. 
У розробленій системі системний промпт [11] сформульовано так: 
prompt = ( "You parse resume text into strict JSON for an ATS. "
"Return only valid JSON object without markdown.\n" "Fields:\n" "{\n"
'  "first_name": string,\n' '  "last_name": string,\n' '  "email": 
string,\n' '  "experience_years": number or null,\n' '  "skills": 
string[],\n' '  "current_company": string,\n'     '  "current_position": 
string\n' "}\n" "If unknown, keep empty string or null." ) 
Рисунок 1.4 – Системний промпт (system prompt) для LLM-парсингу резюме 
1.3.3. OpenRouter як уніфікований шлюз до LLM 
OpenRouter — хмарний API-шлюз, що надає уніфікований інтерфейс 
(сумісний з форматом OpenAI API) до понад 200 мовних моделей від різних 
провайдерів: OpenAI, Anthropic, Google DeepMind, Meta, Mistral AI та інших [12]. 
Ключові переваги: підтримка безкоштовних моделей без обмежень за кількістю 
запитів; автоматичний failover при недоступності основної моделі; єдиний endpoint 
для всіх моделей; параметр response_format: {"type": "json_object"} для 
гарантованого JSON-виводу. 
18 
ЧДТУ 262247.008 ПЗ 
1.3.4. Витяг тексту з PDF-документів 
PDF є найпоширенішим форматом резюме. Для програмного витягу тексту в 
Python наявні дві основні бібліотеки [13]: pypdf (версія 6.x) — сучасний активно 
підтримуваний форк з покращеною продуктивністю та PyPDF2 — попередня 
версія, що підтримується як резервний варіант. 
1.4. Обґрунтування вибору технологічного стеку 
1.4.1. Python та Django REST Framework 
Python є провідною мовою для розробки AI-застосунків та веб-сервісів. 
Django REST Framework (DRF) надає потужний інструментарій для швидкої 
розробки RESTful API: ModelViewSet з автоматичним CRUD, Serializer для 
валідації та трансформації даних, Permission-класи для авторизації [14]. Природна 
інтеграція Python-екосистеми з бібліотеками для роботи з PDF (pypdf) та HTTP-
запитів (urllib.request) робить Python оптимальним вибором для серверної частини. 
1.4.2. React 19 та TypeScript 
React є провідною JavaScript-бібліотекою для розробки SPA (Single Page 
Application). React 19, застосований у даному проєкті, забезпечує покращену 
продуктивність завдяки вбудованому компілятору. TypeScript додає статичну 
типізацію [30], що суттєво покращує якість коду та зменшує кількість помилок під 
час розробки [15]. Vite 8.0.4 використовується як білдер [31] з підтримкою HMR 
(Hot Module Replacement) для прискорення циклу розробки. 
1.4.3. PostgreSQL 
PostgreSQL — найбільш функціональна відкрита реляційна СУБД з 
підтримкою JSON-полів, складних запитів, транзакцій, повнотекстового пошуку та 
перевірних обмежень (CHECK constraints) на рівні БД [16]. Є оптимальним 
вибором для HR-систем, де необхідна надійна обробка взаємопов'язаних даних із 
гарантіями цілісності та підтримкою транзакцій. 
19 
ЧДТУ 26247.008 ПЗ 
ВИСНОВКИ ДО ПЕРШОГО РОЗДІЛУ 
У першому розділі проведено аналіз предметної галузі, огляд існуючих 
рішень та дослідження сучасних AI-методів у сфері управління персоналом. 
Встановлено, що автоматизація охоплює чотири ключові HR-процеси: рекрутинг, 
управління персоналом, облік відпусток та аудит операцій. За даними McKinsey [3] 
та Deloitte [1], впровадження систем автоматизації дозволяє скоротити 
адміністративні витрати на 20 –40 %, звільняючи до 60 % робочого часу фахівців для 
стратегічних завдань. 
Порівняльний аналіз платформ Workday [6], BambooHR [7] та SAP 
SuccessFactors [8] показав, що жодна з них не є оптимальною для українського МСБ 
через надмірну вартість, відсутність локалізації або обмежений AI-функціонал. Це 
обґрунтовує доцільність розробки власного рішення. 
Досліджено еволюцію методів аналізу резюме: класичні NLP-підходи (NER 
[21], Word2Vec [44], CRF [23]) поступаються LLM-моделям на базі архітектури 
трансформера [10 ], які забезпечують структурований витяг даних без спеціального 
навчання. Техніка prompt engineering [11] з параметром temperature=0  гарантує 
детермінований JSON-вивід, а платформа OpenRouter [12] надає безкоштовний 
доступ до понад 20 0  моделей, що забезпечує нульову операційну вартість AI-
модуля. 
Обґрунтовано технологічний стек: Python 3.11 [58] / Django REST Framework 
[14] / React 19 [15] / PostgreSQL 16 [16] / SimpleJWT [29] / Vite [31] — як оптимальне 
поєднання для реалізації поставлених завдань відповідно до сучасних тенденцій 
HR-технологій [5]. 
20 
ЧДТУ 262247.008 ПЗ 
РОЗДІЛ 2. ВПРОВАДЖЕННЯ РЕЗУЛЬТАТІВ ДОСЛІДЖЕНЬ У 
ПРАКТИКУ ПРОЄКТУВАННЯ ПРОГРАМНОГО ЗАБЕЗПЕЧЕННЯ 
ІНФОРМАЦІЙНИХ СИСТЕМ 
2.1. Моделювання предметної області 
Моделювання предметної галузі є визначальним етапом проектування 
програмної системи. Метою побудови моделі є отримання графічного 
відображення логічної структури досліджуваної предметної галузі, що ілюструє 
сутності у формі класів та їх взаємозв'язки. 
2.1.1. Предметна область моделювання. Модель предметної області. Словник 
предметної області 
Предметна область моделювання: програмна система автоматизації HR-
процесів підприємства, що охоплює рекрутинг кандидатів з AI-парсингом резюме, 
управління кадровим складом та організаційною структурою, облік відпусток з 
автоматичним перерахунком балансу та аудит критичних операцій. 
Модель предметної області: системи автоматизації HR-процесів відображає 
сукупність сутностей, їх атрибутів та зв'язків, що описують ключові об'єкти 
управління персоналом підприємства. До основних сутностей належать: 
користувач (User), профіль співробітника (EmployeeProfile), заявка на відпустку 
(LeaveRequest), баланс відпусток (LeaveBalance), вакансія (Vacancy), кандидат 
(Candidate) та заявка кандидата (Application). 
Центральною сутністю є User, від якої через зв'язки успадкування та асоціації 
будуються всі підсистеми: модуль управління персоналом, модуль відпусток і 
модуль рекрутингу. Всі критичні операції над сутностями фіксуються в журналі 
AuditEvent для забезпечення аудиту дій користувачів. 
Словник предметної області системи автоматизації HR-процесів охоплює 
такі основні сутності: 
21 
ЧДТУ 262247.008 ПЗ 
– користувач (User) — зареєстрований суб'єкт з email як логіном та
призначеною роллю. Розширює стандартну модель AbstractUser Django.
Поле role визначає рівень доступу: admin, hr-manager або employee;
– відділ (Department) — структурна одиниця підприємства з унікальним
найменуванням та кодом. Може включати декілька посад та
співробітників.
– посада (Position) — штатна одиниця з унікальним кодом, що визначає
функціональну роль у відповідному відділі;
– профіль співробітника (EmployeeProfile) — детальна картка: особисті
дані, унікальний табельний номер (EMP-XXXXX), відділ, посада,
безпосередній керівник (ієрархія), дата найму, зарплата, статус
зайнятості;
– поліс відпусток (LeavePolicy) — конфігурація типу відпустки: кількість
днів на рік, перенесення залишку, потреба у затвердженні;
– баланс відпусток (LeaveBalance) — облік доступних (total_days),
використаних (used_days) та очікуваних (pending_days) днів за кожним
типом та роком;
– заявка на відпустку (LeaveRequest) — запит на відпустку визначеного
типу на вказаний період. Проходить цикл станів: PENDING →
APPROVED / REJECTED / CANCELLED;
– журнал затверджень (LeaveApprovalLog) — запис кожної дії з заявкою:
хто, коли і з яким коментарем;
– вакансія (Vacancy) — відкрита позиція для найму. Можливі статуси:
DRAFT, OPEN, PAUSED, CLOSED, FILLED;
– кандидат (Candidate) — особа-претендент. Зберігаються контактні дані,
навички (technologies), досвід, поточна компанія та посада;
– заявка кандидата (Application) — зв'язок між кандидатом та вакансією.
Поле stage відображає поточну стадію рекрутингу. При stage=HIRED
автоматично зв'язується з EmployeeProfile;
22 
ЧДТУ 262247.008 ПЗ 
– співбесіда (Interview) — запланована або проведена зустріч з кандидатом.
Типи: HR, Tech, Manager, Final. Зберігається рекомендація: strong-hire /
hire / hold / reject;
– нотатка (RecruitmentNote) — коментар рекрутера до заявки кандидата;
– подія аудиту (AuditEvent) — запис критичної операції: хто (actor), що
(action),   з якою сутністю (entity_type + entity_id), з якими даними
(metadata JSON).
2.1.2. Елементи моделювання предметної області 
Модель предметної галузі системи представлена у вигляді діаграми класів 
аналітичного рівня. Центральними об'єктами є User та EmployeeProfile (пов'язані 
відношенням OneToOne), що є точкою інтеграції між підсистемами автентифікації, 
управління персоналом та рекрутингу. Модуль відпусток повністю пов'язаний з 
EmployeeProfile. Підсистема рекрутингу містить Vacancy, Candidate та Application 
як центральні об'єкти з підпорядкованими Interview та RecruitmentNote. 
Рисунок 2.1 – Модель предметної галузі системи автоматизації HR-процесів 
23 
ЧДТУ 262247.008 ПЗ 
2.1.3. Робоча область моделювання 
Для моделювання предметної галузі та проектування всієї системи в даній 
роботі використовується мова UML (Unified Modeling Language)[35]. У таблиці 2.1 
наведено основні графічні елементи UML, застосовані в діаграмах. 
Таблиця 2.1 
Основні UML-елементи моделювання 
Графічний елемент Назва та призначення 
Прямокутник з трьома секціями Клас — ім'я, атрибути, операції 
Фігурка «людини» Актор (Actor) — зовнішній суб'єкт системи 
Еліпс Варіант використання (Use Case) 
Суцільна лінія зі стрілкою Асоціація / відношення між об'єктами 
Суцільна лінія з трикутником Узагальнення (наслідування) 
Пунктирна лінія зі стрілкою Залежність / реалізація інтерфейсу 
Ромб на лінії Агрегація / композиція 
Прямокутник (вузол) Вузол розгортання (Deployment Diagram) 
Аналіз інформаційних потоків системи 
Детальний аналіз інформаційної моделі системи дозволяє виокремити такі 
основні потоки даних (див. рис 2.2): 
24 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.2 – Схема інформаційних потоків системи 
– автентифікація — перевірка email + password, видача JWT access + refresh
токенів, автоматичне оновлення access-токена при отриманні відповіді
401 Unauthorized;
– CRUD-операції — HTTP-запити від React SPA до REST API із заголовком
Bearer-авторизації. ORM Django транслює запити в SQL до PostgreSQL;
– AI-парсинг резюме — завантаження PDF → витяг тексту → HTTP POST
до OpenRouter API → JSON-відповідь → збереження Candidate +
Application;
– управління відпустками — заявка → перевірка балансу → оновлення
LeaveBalance → запис у LeaveApprovalLog → фіксація в AuditEvent.
2.2. Формування та аналіз вимог 
2.2.1. Формування вимог до програмного забезпечення. Первинні і детальні 
вимоги. Вимоги замовника і розробника. Функціональні та нефункціональні 
вимоги 
25 
ЧДТУ 262247.008 ПЗ 
Формування вимог є ключовим етапом [36] [37] [50] розробки програмного 
забезпечення, що визначає подальшу архітектуру системи та критерії її успіху. 
Вимоги поділяються за типом походження на первинні (від замовника) та детальні 
(від розробника), а за функціональним призначенням — на функціональні та 
нефункціональні. 
Первинні вимоги замовника. Первинні вимоги формулюються на рівні 
бізнес-задач без технічних деталей реалізації та описують очікуваний результат з 
точки зору користувача: 
– система повинна автоматично заповнювати картку кандидата при
завантаженні PDF-резюме, усуваючи ручне введення даних;
– HR-менеджер повинен спостерігати стадії рекрутингу всіх кандидатів на
одному екрані у форматі Kanban-дошки [52];
– система повинна автоматично відстежувати залишок відпускних днів та
блокувати подання заявки при перевищенні ліміту;
– адміністратор повинен мати повний контроль над ролями користувачів і
журналом аудиту дій;
– система повинна забезпечувати рольове розмежування доступу між
співробітником, HR-менеджером та адміністратором;
– інтерфейс повинен бути україномовним і зручним для щоденного
використання без технічної підготовки.
Детальні вимоги розробника. Детальні вимоги уточнюють первинні на 
технічному рівні та визначають конкретні механізми реалізації. За підсистемами 
системи вони такі: 
Автентифікація та авторизація: 
– система автентифікує за email + паролем через POST /api/accounts/login/
та повертає {access, refresh, user};
– access-токен діє 60 хвилин, refresh-токен — 7 днів; при HTTP 401 клієнт
автоматично оновлює access через POST /api/accounts/refresh/;
– Permission-класи (IsAdminRole, IsHRManagerRole, IsAdminOrHRManager)
перевіряють поле role при кожному запиті.
26 
ЧДТУ 262247.008 ПЗ 
AI-парсинг резюме: 
– ендпоінт POST /api/recruitment/cv-parse/ приймає FormData з полями
cv_file (PDF) та vacancy_id;
– текст резюме витягується через pypdf (резерв PyPDF2) та передається до
OpenRouter API для структурованого JSON-парсингу;
– при HTTP 429 виконується до 3 повторних спроб із затримками 1.2, 2.4 та
3.6 секунди (exponential backoff)[12];
– при недоступності AI активується regex-парсер fallback_parse_cv_text();
список навичок нормалізується до 30 елементів.
Управління відпустками: 
– LeaveRequest при створенні автоматично обчислює working_days (Пн–
Пт), при затвердженні перевіряється умова working_days ≤ available_days;
– LeaveBalance перераховується при кожній зміні статусу заявки;
LeaveApprovalLog фіксує кожну дію HR-менеджера.
Рекрутинг: 
– при stage=HIRED для Application метод
_get_or_create_employee_from_application() в межах @transaction.atomic
створює User та EmployeeProfile;
– EmploymentHistory.create() фіксує момент найму з нотаткою «Hired via
recruitment application #{id}».
Функціональні вимоги. Функціональні вимоги визначають конкретні дії, 
які система виконує в межах кожного модуля. Вони сформовані у вигляді 
одинадцяти варіантів використання: 
– UC-01: автентифікація — вхід за email + паролем, отримання JWT-пари,
рольове перенаправлення;
– UC-02: перегляд Dashboard — статистичні картки, глобальний пошук,
календар відпусток;
– UC-03: управління персоналом — CRUD профілів співробітників,
відділів і посад, побудова ієрархії;
27 
ЧДТУ 262247.008 ПЗ 
– UC-04: подання заявки на відпустку — вибір типу і дат, автоматичний
розрахунок робочих днів, перевірка балансу;
– UC-05: розгляд заявки HR-менеджером — затвердження або відхилення з
коментарем, перерахунок LeaveBalance;
– UC-06: скасування заявки — співробітник або HR повертає дні до
балансу;
– UC-07: управління вакансіями — CRUD вакансій з прив'язкою до відділу
та посади;
– UC-08: AI-парсинг PDF-резюме — завантаження, парсинг, автоматичне
створення Candidate та Application;
– UC-09: Kanban-дошка рекрутингу [52] — перегляд і переміщення
кандидатів між стадіями, планування співбесід;
– UC-10: найм кандидата — stage=hired, автоматичне створення облікового
запису та профілю співробітника;
– UC-11: управління ролями — зміна ролей і статусів користувачів,
перегляд журналу AuditEvent.
Нефункціональні вимоги. Нефункціональні вимоги визначають 
характеристики системи, що забезпечують її стабільну, безпечну та зручну роботу. 
Основні з них: 
– продуктивність: час відповіді REST API ≤ 200 мс для стандартних CRUD-
операцій при навантаженні до 50 одночасних користувачів;
– продуктивність: AI-парсинг ≤ 10 сек, regex-fallback ≤ 0.5 сек для PDF до 5
МБ;
– безпека: паролі хешуються PBKDF2 (Django); SQL-ін'єкції виключені
ORM; CORS обмежено до localhost:5173;
– надійність: @transaction.atomic при наймі кандидата та AI-парсингу;
exponential backoff при HTTP 429;
– надійність: CHECK-constraints у БД — salary ≥ 0, end_date ≥ start_date,
used_days ≤ total_days;
28 
ЧДТУ 262247.008 ПЗ 
– масштабованість: stateless REST API дозволяє горизонтальне 
масштабування; складені індекси оптимізують запити; 
– аудит: всі критичні операції фіксуються в AuditEvent (actor, action,
entity_type, entity_id, metadata) без автоматичного видалення.
Сукупність сформованих вимог визначає повну специфікацію системи 
автоматизації HR-процесів та є основою для проектування архітектури і розробки 
програмного забезпечення. 
Основні нефункціональні вимоги[37][34] до системи наведено в таблиці 2.2. 
Таблиця 2.2 
 Нефункціональні вимоги до системи 
Категорія Вимога 
Продуктивність Час відповіді REST API ≤ 200 мс для стандартних операцій 
(без AI). AI-парсинг — ≤ 30 сек (тайм-аут urllib). 
Безпека Паролі хешуються Django (PBKDF2). SQL-ін'єкції виключені 
через ORM. CORS обмежений localhost:5173. XSS-захист 
React. 
Надійність AI Exponential backoff (до 3 спроб). Fallback regex-парсер при 
недоступності AI. Placeholder email при відсутності у CV. 
Масштабованість Stateless REST API дозволяє горизонтальне масштабування. 
CONN_MAX_AGE=60 для пулу з'єднань БД. 
Зручність Україномовний інтерфейс SPA. Адаптивний дизайн. Час 
відгуку UI < 100 мс. 
Аудит Всі критичні операції логуються в AuditEvent зі збереженням: 
хто, що, коли, з якими даними. 
29 
ЧДТУ 262247.008 ПЗ 
2.2.2. Формування вимог за допомогою діаграми прецедентів 
Діаграма прецедентів відображає взаємодію трьох акторів системи з 
функціональними варіантами використання. Адміністратор (Admin) має 
необмежений доступ до всіх функцій. HR-менеджер може керувати персоналом, 
рекрутингом та відпустками. Співробітник (Employee) має доступ лише до 
власного профілю та заявок на відпустку. 
Визначено такі варіанти використання системи: 
– UC-01: Автентифікація (POST /api/accounts/login/) — Всі ролі;
– UC-02: Перегляд Dashboard зі статистикою та глобальним пошуком — Всі
ролі;
– UC-03: Управління персоналом (GET/POST/PATCH 
/api/employees/profiles/) — Admin / HR;
– UC-04: Подання заявки на відпустку (POST /api/leaves/requests/) — Всі
ролі;
– UC-05: Затвердження / відхилення заявки (POST .../review/) — Admin /
HR;
– UC-06: Скасування заявки (POST .../cancel/) — Власник або Admin/HR;
– UC-07: Управління вакансіями (CRUD /api/recruitment/vacancies/) —
Admin / HR;
– UC-08: Kanban-дошка [52] кандидатів (GET /api/recruitment/applications/) —
Admin / HR;
– UC-09: AI-парсинг резюме (POST /api/recruitment/cv-parse/) — Admin /
HR;
– UC-10: Найм кандидата (PATCH .../stage: hired) — Admin / HR;
– UC-11: Управління ролями (PATCH /api/accounts/users/{id}/role/) —
Admin.
30 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.3 – Діаграма прецедентів системи автоматизації HR-процесів модуля 
Акаунт 
Рисунок 2.4 – Діаграма прецедентів системи автоматизації HR-процесів модуля 
Працівники 
31 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.5 – Діаграма прецедентів системи автоматизації HR-процесів модуля 
Відпустки 
32 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.6 – Діаграма прецедентів системи автоматизації HR-процесів модуля 
Рекрутинг 
2.3. Проектування логічної структури програмного комплексу 
Загальна архітектура системи 
Система побудована за трирівневою клієнт-серверною архітектурою 
REST.[24][43] Перший рівень — React SPA (браузер), що відображає UI та надсилає 
HTTP-запити. Другий рівень — Django REST API (сервер), що реалізує бізнес-
33 
ЧДТУ 262247.008 ПЗ 
логіку, авторизацію та AI-інтеграцію. Третій рівень — PostgreSQL (БД), що 
зберігає всі дані. Зовнішній сервіс — OpenRouter API для LLM-запитів. 
Конфігурація Django (settings.py) визначає глобальні параметри 
автентифікації та JWT-токенів[29] [49] та CORS [40]: 
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'AUTH_HEADER_TYPES': ('Bearer',), 
} 
Рисунок 2.7 – Конфігурація JWT-автентифікації в settings.py 
2.3.1. Діаграми класів 
Статична структура системи описується чотирма детальними діаграмами 
класів — по одній на кожний Django-застосунок: accounts, employees, leaves, 
recruitment. Загальну взаємодію між модулями ілюструє зведена системна діаграма 
(рисунок 2.3). Кожен модуль реалізує власний домен предметної галузі й взаємодіє 
з іншими виключно через чітко визначені зовнішні ключі та сервісні класи. 
34 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.8 – Загальна діаграма класів системи 
Модуль accounts. Модуль реалізує автентифікацію, рольову модель та 
журналювання дій. Детальна діаграма класів модуля наведена на рисунку 2.9. 
– AbstractUser «Django» — базовий клас Django із полями: id, username,
first_name, last_name, is_active, is_staff, date_joined; методами
set_password(raw) та check_password(raw): bool. Є батьківським класом для
User через механізм спадкування;
35 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.9 – Діаграма класів модуля accounts 
– User — розширює AbstractUser двома полями: email (EmailField, unique,
USERNAME_FIELD), role (str, choices: admin / hr-manager / employee).
Метод __str__() : str. Перелік допустимих ролей описано перерахуванням
Role;
– Role «enumeration» — описує ролі користувачів системи: ADMIN =
"admin", HR_MANAGER = "hr-manager", EMPLOYEE = "employee";
– AuditEvent — фіксує критичні операції користувачів. Поля: id, actor
(FK<User>, nullable — системні події), action (str, max 120, описова мітка,
напр. "leave.approved"), entity_type (str, max 120, назва сутності, напр.
"LeaveRequest"), entity_id (str, max 64), metadata (JSONField — довільні
додаткові дані), created_at (datetime). Складені індекси: (action, created_at)
та (entity_type, entity_id) для ефективної фільтрації журналу;
Класи дозволів (Permission-ієрархія): 
– HasRole «Permission» — базовий клас рольових Permission-класів DRF.
Поле: allowed_roles (tuple). Метод: has_permission(request, view): bool —
36 
ЧДТУ 262247.008 ПЗ 
перевіряє, чи роль аутентифікованого користувача входить до 
allowed_roles; 
– IsAdminRole — підклас HasRole з allowed_roles = ("admin",). Надає доступ
виключно адміністраторам;
– IsHRManagerRole — підклас HasRole з allowed_roles = ("hr-manager",).
Надає доступ HR-менеджерам;
– IsAdminOrHRManager — підклас HasRole з allowed_roles = ("admin", "hr-
manager"). Надає доступ обом привілейованим ролям;
– IsAdminOrHRManagerOrReadOnly — незалежний клас Permission з
методом has_permission(request, view): bool. Дозволяє GET-запити будь-
якому аутентифікованому користувачу, а модифікуючі запити — лише
admin або hr-manager.
Модуль employees. Модуль відповідає за організаційну ієрархію 
підприємства та профілі співробітників. Детальна діаграма класів наведена на 
рисунку 2.10. 
– Department — відділ організації. Поля: id, name (str, unique), code (str,
unique, max 20), description (text), is_active (bool), created_at, updated_at.
Метод __str__(): str;
– Position — штатна посада. Поля: id, title (str), code (str, unique, max 30),
description (text), is_active (bool), created_at, updated_at. Метод __str__():
str;
– EmployeeProfile — розширений профіль співробітника. Поля: id, user
(OneToOne<User>), employee_number (str, unique, формат EMP-XXXXX),
department (FK<Department>), position (FK<Position>), manager 
(FK<EmployeeProfile>, self — ієрархія керівників, nullable), 
employment_type (str, choices: EmploymentType), employment_status (str, 
choices: EmploymentStatus), hire_date (date), termination_date (date, 
nullable), birth_date (date, nullable), phone (str), emergency_contact_name 
(str), emergency_contact_phone (str), address (str), salary (Decimal, ≥ 0), 
created_at, updated_at. Метод __str__(): str; 
37 
ЧДТУ 262247.008 ПЗ 
– EmploymentHistory — журнал змін посади/відділу співробітника. Поля:
id, employee (FK<EmployeeProfile>), department (FK<Department>),
position (FK<Position>), manager (FK<EmployeeProfile>, nullable),
started_at (date), ended_at (date, nullable), note (text), created_at. Обмеження
CHECK: ended_at ≥ started_at. Метод __str__(): str;
Рисунок 2.10 – Діаграма класів модуля employees 
38 
ЧДТУ 26247.008 ПЗ 
Перерахування модуля employees: 
– EmploymentType — тип зайнятості: FULL_TIME = "full-time",
PART_TIME = "part-time", CONTRACT = "contract", INTERN = "intern";
– EmploymentStatus — статус зайнятості: ACTIVE = "active", PROBATION
= "probation", ON_LEAVE = "on-leave", TERMINATED = "terminated".
Модуль leaves — управління відпустками 
Модуль реалізує повний цикл управління відпустками: від налаштування 
полісів і балансів до подання, розгляду та журналювання заявок. Детальна діаграма 
класів наведена на рисунку 2.11. 
– LeavePolicy — налаштування правил відпустки для кожного типу. Поля: id,
name (str, unique), leave_type (str, choices: LeaveType), annual_days (int — ліміт на 
рік), carryover_days (int — перенесення залишку), requires_approval (bool), is_active 
(bool), created_at, updated_at. Метод __str__(): str; 
– LeaveBalance — поточний баланс відпустки співробітника за рік. Поля: id,
employee (FK<EmployeeProfile>), leave_type (str), year (int), total_days (Decimal), 
used_days (Decimal), pending_days (Decimal), updated_at. Обмеження: 
UNIQUE(employee, leave_type, year); CHECK: used_days ≤ total_days. Метод 
__str__(): str; 
– LeaveRequest — заявка на відпустку. Поля: id, employee 
(FK<EmployeeProfile>), leave_type (str, choices: LeaveType), status (str, choices: 
LeaveRequestStatus), start_date (date), end_date (date), working_days (Decimal — 
автоматично підраховується), reason (text), approved_by (FK<User>, nullable), 
approved_at (datetime, nullable), rejection_reason (text), created_at, updated_at. Метод 
__str__(): str; 
– LeaveApprovalLog — журнал рішень по заявці. Поля: id, leave_request
(FK<LeaveRequest>, "1..*"), action (str, choices: LogAction), actor (FK<User>), 
comment (text), created_at. Метод __str__(): str. 
39 
ЧДТУ 262247.008 ПЗ 
Перерахування модуля leaves: 
– LeaveType — тип відпустки: VACATION = "vacation", SICK = "sick",
UNPAID = "unpaid", MATERNITY = "maternity", PATERNITY = "paternity", OTHER 
= "other"; 
– LeaveRequestStatus — статус заявки: PENDING = "pending", APPROVED =
"approved", REJECTED = "rejected", CANCELLED = "cancelled"; 
– LogAction — тип дії у журналі: CREATED = "created", SUBMITTED =
"submitted", APPROVED = "approved", REJECTED = "rejected", CANCELLED = 
"cancelled". 
Рисунок 2.11 – Діаграма класів модуля leaves 
40 
ЧДТУ 262247.008 ПЗ 
Модуль recruitment — рекрутинг та AI-парсинг резюме 
Модуль реалізує повний цикл підбору персоналу: від розміщення вакансії до 
найму кандидата з автоматичним створенням облікового запису. Ключовою 
особливістю є сервісний клас CVParsingService, який інтегрує AI-обробку PDF-
резюме. Детальна діаграма класів наведена на рисунку 2.12. 
– CVParsingService «service»[25][27] — сервісний клас, що інкапсулює
логіку AI-парсингу резюме. Не є Django-моделлю. Методи:
extract_pdf_text(file): str — витягує текст із PDF через бібліотеку pypdf;
parse_cv_with_openrouter(cv_text, api_key, model): dict — надсилає запит
до LLM через OpenRouter API з механізмом exponential backoff (до 3
спроб при HTTP 429); fallback_parse_cv_text(text): dict — regex-парсер як
резервний механізм при недоступності API;
fetch_openrouter_free_model_ids(api_key, limit): list — отримує та кешує
(TTL 3600 с) список безкоштовних моделей OpenRouter;
– Vacancy — вакансія підприємства. Поля: id, title (str), code (str, unique),
department (FK<Department>), position (FK<Position>), status (str, choices:
VacancyStatus), location (str), description (text), salary_from (Decimal,
nullable), salary_to (Decimal, nullable), opened_at (datetime), closed_at
(datetime, nullable), created_by (FK<User>), created_at, updated_at.
Обмеження CHECK: salary_to ≥ salary_from. Метод __str__(): str;
– Candidate — профіль кандидата, може бути заповнений вручну або через
CVParsingService. Поля: id, first_name (str), last_name (str), email
(EmailField, unique), phone (str), source (str, choices: CandidateSource),
linkedin_url (URL, nullable), portfolio_url (URL, nullable), experience_years
(Decimal, nullable), expected_salary (Decimal, nullable), current_company
(str), current_position (str), technologies (text — рядок навичок, до 30
елементів після нормалізації), notes (text), created_at, updated_at. Метод
__str__(): str;
– Application — заявка кандидата на вакансію. Поля: id, candidate
(FK<Candidate>), vacancy (FK<Vacancy>), stage (str, choices: 
41 
ЧДТУ 262247.008 ПЗ 
ApplicationStage), assigned_recruiter (FK<User>, nullable), score (Decimal 
[0–100], nullable), resume_url (URL, nullable), cover_letter (text), 
hired_employee (OneToOne<EmployeeProfile>, nullable — заповнюється 
при stage=hired), applied_at (datetime), updated_at. Обмеження 
UNIQUE(candidate, vacancy). Метод __str__(): str; 
– Interview — співбесіда за заявкою. Поля: id, application (FK<Application>),
interviewer (FK<User>), interview_type (str, choices: InterviewType), status
(str, choices: InterviewStatus), recommendation (str, choices:
Recommendation, nullable), scheduled_at (datetime), duration_minutes (int,
nullable), feedback (text), created_at, updated_at. Метод __str__(): str;
– RecruitmentNote — довільна нотатка рекрутера по заявці. Поля: id,
application (FK<Application>), author (FK<User>), note (text), created_at.
Метод __str__(): str.
Перерахування модуля recruitment: 
– VacancyStatus — статус вакансії: DRAFT = "draft", OPEN = "open",
PAUSED = "paused", CLOSED = "closed", FILLED = "filled";
– CandidateSource — джерело кандидата: LINKEDIN = "linkedin",
JOB_PORTAL = "job-portal", REFERRAL = "referral", WEBSITE =
"website", OTHER = "other";
– ApplicationStage — стадія воронки: APPLIED = "applied", SCREENING =
"screening", INTERVIEW = "interview", TEST_TASK = "test-task", OFFER
= "offer", HIRED = "hired", REJECTED = "rejected";
– InterviewType — тип співбесіди: HR = "hr", TECH = "tech", MANAGER =
"manager", FINAL = "final";
– InterviewStatus — статус співбесіди: SCHEDULED = "scheduled",
COMPLETED = "completed", CANCELLED = "cancelled", NO_SHOW =
"no-show";
– Recommendation — рекомендація після співбесіди: STRONG_HIRE =
"strong-hire", HIRE = "hire", HOLD = "hold", REJECT = "reject".
42 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.12 – Діаграма класів модуля recruitment 
43 
ЧДТУ 262247.008 ПЗ 
2.3.2. Діаграма пакетів 
Фронтенд-пакети (src/): app/router (AppRouter, paths), components/auth, 
components/ui, pages (8 функціональних модулів), store (authStore), utils (apiClient, 
formatDate, calculateDays, errors), types (user, leave, roles). 
Бекенд-пакети: config (settings, urls, wsgi), accounts (models, permissions, 
serializers, views, audit), employees (models, serializers, views), leaves (models, 
serializers, views), recruitment (models, serializers, views, cv_parsing). 
Рисунок 2.13 – Діаграма пакетів системи 
44 
ЧДТУ 262247.008 ПЗ 
2.4. Архітектурне проектування 
2.4.1. Діаграма компонентів 
Система складається з таких архітектурних компонентів: 
– React SPA — клієнтський застосунок у браузері. Підкомпоненти:
authStore (pub/sub[25][27] стан автентифікації), apiClient (HTTP з auto-
refresh JWT), сторінки (8 функціональних модулів).
– Django REST API — серверний застосунок. Підкомпоненти: Middleware
(CORS, Security, Auth), застосунки (accounts, employees, leaves,
recruitment), ORM (Django → PostgreSQL).
– cv_parsing module — AI-модуль. Залежності: pypdf, urllib.request →
OpenRouter.
– PostgreSQL — СУБД. Схема: 12 таблиць у 4 логічних групах.
– OpenRouter API Gateway — зовнішній сервіс. Надає доступ до LLM через
HTTPS.
Рисунок 2.14 – Діаграма компонентів системи 
45 
ЧДТУ 262247.008 ПЗ 
2.4.2. Розгортання програмної системи на апаратних засобах. Діаграма 
розгортання 
Розгортання системи охоплює такі вузли: 
– браузер користувача — виконує React SPA. Взаємодіє через HTTP/HTTPS
з сервером на порту 5173 (dev) або 443 (prod);
– сервер застосунку (Django) — обробляє HTTP-запити. Порт 8000 у
режимі розробки (python manage.py runserver). У production: Gunicorn +
Nginx;
– сервер PostgreSQL — зберігає дані. Порт 5432. Підключення через
psycopg [41] з CONN_MAX_AGE=60;
– OpenRouter Cloud — HTTPS-сервіс для LLM. URL: 
https://openrouter.ai/api/v1/chat/completions, тайм-аут 45 сек.
Рисунок 2.15 – Діаграма розгортання системи 
46 
ЧДТУ 262247.008 ПЗ 
2.5. Моделювання поведінки системи 
Для опису динаміки роботи системи автоматизації HR-процесів розроблено 
чотири діаграми діяльності (Activity Diagram). Кожна з них описує конкретний 
бізнес-процес у нотації UML 2.5 [35]: ініціюючу подію, послідовність дій, 
розгалуження за умовами та кінцевий стан. Діаграми охоплюють усі ключові 
сценарії взаємодії користувачів із системою та відображають точки прийняття 
рішень, обробки помилок і зовнішньої інтеграції з OpenRouter API. 
2.5.1. Діаграма діяльності 
Діаграма діяльності «Процес AI-парсингу резюме»: 
Наведена на рисунку 2.16 діаграма описує повний цикл завантаження та 
автоматичної обробки PDF-резюме кандидата з використанням великої мовної 
моделі (LLM) через OpenRouter API. 
Процес ініціюється, коли HR-менеджер відкриває картку кандидата та 
завантажує PDF-файл резюме, вказуючи ідентифікатор відповідної вакансії. 
Клієнтський застосунок формує multipart-запит до ендпоінту POST 
/api/recruitment/cv/parse/. На серверній стороні виконуються два послідовні кроки 
валідації вхідних даних: 
– перевірка наявності та формату файлу — якщо файл відсутній або не є
PDF, повертається помилка валідації HTTP 400;
– перевірка існування вакансії в базі даних за переданим ідентифікатором —
якщо вакансія не знайдена, також повертається HTTP 400.
Після успішного проходження обох перевірок бібліотека pypdf витягує 
текстовий зміст з усіх сторінок PDF-файлу. [13] Подальший маршрут обробки 
залежить від наявності налаштованого ключа OPENROUTER_API_KEY: 
– якщо ключ відсутній (пунктирна гілка) — виконання одразу переходить до
резервного парсингу;
– якщо ключ наявний — система отримує актуальний список безкоштовних
AI-моделей (результат кешується на 3600 секунд), після чого починається
цикл по доступних моделях.
47 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.16 – Діаграма діяльності: процес AI-парсингу резюме 
48 
ЧДТУ 262247.008 ПЗ 
У межах циклу кожна модель отримує текст резюме через API OpenRouter. 
Якщо API повертає HTTP 429 (перевищення ліміту запитів), активується механізм 
exponential backoff [12]: виконання затримується і здійснюється повторна спроба 
для поточної моделі (до 3 разів). Якщо жодна з моделей не повернула успішний 
результат, процес переходить до резервного парсингу за допомогою регулярних 
виразів (regex). 
Незалежно від шляху отримання структурованих даних (AI або regex), 
подальші кроки є однаковими: 
– виконується get_or_create для об'єкта Candidate за унікальним ключем
email — якщо кандидат уже існує, його профіль оновлюється; якщо ні —
створюється новий запис із вилученими полями (ім'я, прізвище, телефон,
список технологій, досвід);
– аналогічно виконується get_or_create для об'єкта Application з початковим
статусом «applied»;
– у журнал аудиту записується подія з інформацією про те, чи
використовувався AI-парсинг та яка саме модель надала результат.
Діаграма діяльності «Процес авторизації» 
Діаграма на рисунку 2.17 описує процес входу користувача до системи з 
використанням JWT-автентифікації та рольового перенаправлення. 
Процес починається з того, що користувач відкриває сторінку входу та 
вводить свої облікові дані — email і пароль. Клієнт надсилає їх у тілі POST-запиту 
до ендпоінту /api/accounts/login/. Сервер перевіряє відповідність наданих даних 
записам у базі даних: 
– якщо дані невалідні — повертається HTTP 401 з повідомленням «Невірні
дані», форма входу очищується і користувач може повторити спробу; 
– якщо дані валідні — сервер генерує пару JWT-токенів: короткоживучий
access-токен (термін дії 60 хвилин) та довгоживучий refresh-токен (термін дії 7 
днів). 
49 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.17 – Діаграма діяльності: процес авторизації 
50 
ЧДТУ 262247.008 ПЗ 
Після отримання токени зберігаються на стороні клієнта (localStorage). 
Подальше перенаправлення залежить від поля role в об'єкті користувача, що 
повертається разом із токенами: 
– employee — перенаправлення на Employee Dashboard із доступом до
особистих заявок на відпустку та профілю;
– hr-manager — перенаправлення на HR Dashboard із повним доступом до
модулів персоналу, відпусток і рекрутингу;
– admin — перенаправлення на Admin Dashboard із додатковим доступом
до управління ролями та системними налаштуваннями.
Механізм автоматичного оновлення access-токена (silent refresh) 
реалізований на рівні HTTP-клієнта: при отриманні відповіді HTTP 401 на будь-
який захищений запит клієнт автоматично надсилає refresh-токен для отримання 
нового access-токена без переривання роботи користувача. 
Діаграма діяльності «Процес подання та розгляду заявки на відпустку» 
Рисунок 2.18 відображає двосторонній процес управління відпустками: від 
подання заявки співробітником до прийняття рішення HR-менеджером із 
відповідним перерахунком балансу. 
Ліва частина діаграми описує дії співробітника. Він обирає тип відпустки 
(vacation / sick / unpaid / maternity / paternity / other) та вводить дати початку і 
закінчення. Система автоматично обчислює кількість робочих днів — функція 
_calculate_working_days() виключає суботи та неділі. Сформована заявка 
надсилається через POST /api/leaves/requests/. Перед збереженням виконується 
перевірка балансу: 
– якщо доступних днів недостатньо — повертається HTTP 400 з
повідомленням «Недостатньо доступних днів», процес завершується;
– якщо баланс достатній — створюється об'єкт LeaveRequest зі статусом
PENDING.
Права частина відображає серверну логіку та дії HR-менеджера. Одразу після 
створення заявки система виконує три паралельні дії: 
– записує LeaveApprovalLog з дією CREATED;
51 
ЧДТУ 262247.008 ПЗ 
– перераховує LeaveBalance: поле pending_days збільшується на кількість
робочих днів заявки;
– записує AuditEvent з міткою «leaves.request.created» та надсилає
сповіщення HR-менеджеру.
HR-менеджер переглядає заявку та приймає рішення через PATCH 
/api/leaves/requests/{id}/review/: 
– відхилення (reject): заявці присвоюється статус REJECTED, записується
LeaveApprovalLog з коментарем, поле pending_days балансу зменшується
— ліміт повертається назад;
– затвердження (approve): заявці присвоюється статус APPROVED,
записується LeaveApprovalLog, баланс перераховується: used_days
збільшується, pending_days зменшується.
Діаграма діяльності «Процес найму кандидата»: 
Діаграма на рисунку 2.19 описує розширений процес рекрутингу — від 
первинного завантаження резюме до автоматичного створення профілю 
співробітника при успішному наймі. Процес структурований у три паралельні 
потоки. 
Лівий потік — парсинг та первинне введення кандидата. HR-менеджер 
завантажує PDF-резюме та обирає вакансію через POST /api/recruitment/cv/parse/. 
Сервер витягує текст за допомогою pypdf. Наявність ключа 
OPENROUTER_API_KEY визначає маршрут: 
– за наявності ключа — викликається parse_cv_with_openrouter() з
перебором доступних моделей та повторними спробами при HTTP 429; за
успіху parse_mode = "ai" [12] ;
– за відсутності ключа або помилки всіх моделей — викликається
fallback_parse_cv_text(), parse_mode = "fallback".
52 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.18 – Діаграма діяльності: процес подання та розгляду заявки на 
відпустку 
53 
ЧДТУ 262247.008 ПЗ 
Після отримання структурованих даних виконується get_or_create Candidate 
за email як унікальним ключем, потім get_or_create Application зі стадією APPLIED, 
і записується AuditEvent «recruitment.cv.parsed». 
Центральний потік — воронка рекрутингу. HR-менеджер переглядає профіль 
кандидата та обирає один із сценаріїв: 
– скринінг: PATCH application stage=screening — HR оцінює відповідність
вимогам і за потреби просуває далі;
– інтерв'ю: POST /api/recruitment/interviews/ для планування зустрічі з
типом (HR / Tech / Manager / Final); після проведення заповнюються поля
feedback та recommendation (strong-hire / hire / hold / reject).
За результатами розгляду HR приймає остаточне рішення: 
– найм: PATCH application stage=hired — тригер для правого потоку;
– відхилення: PATCH application stage=rejected — процес завершується.
Правий потік — автоматичне створення співробітника при наймі. Метод 
_get_or_create_employee_from_application() виконує такі кроки: 
– перевірка, чи існує User з email кандидата: якщо так — оновлюється роль
на employee та профіль; якщо ні — створюється новий User з unusable
password (вхід лише через лист активації);
– ensure_employee_profile(): гарантовано створює EmployeeProfile, 
заповнюючи відділ та посаду із даних вакансії;
– ствоюється запис EmploymentHistory з нотаткою «Hired via 
#{application_id}»; 
– записується AuditEvent «recruitment.application.hired» для повного
журналювання події найму.
Таким чином, процес найму є повністю атомарним: при переведенні 
кандидата до стадії hired система в межах однієї транзакції (@transaction.atomic) 
гарантовано створює всі необхідні записи або скасовує зміни у разі помилки. 
54 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.19 – Діаграма діяльності: процес найму кандидата 
2.5.2. Діаграма послідовності 
Учасники: Користувач → React Login Form → apiClient → Django 
/api/accounts/login/ → PostgreSQL. Послідовність: POST {email, password} → 
CustomTokenObtainPairSerializer.validate() → User.objects.get(email=...) → 
check_password() → відповідь {access, refresh, user} → localStorage.setItem + 
authStore.setAuthUser() → перехід на /dashboard. 
При наступних запитах authorizedRequestJson() автоматично додає заголовок 
Authorization: Bearer {access}. При отриманні 401 — refreshAccessToken() → POST 
/api/accounts/refresh/ → новий access-токен → повторний запит (дедуплікація 
паралельних refresh через refreshPromise). 
55 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.20 – Діаграма послідовності: процес автентифікації 
56 
ЧДТУ 262247.008 ПЗ 
2.5.3. Діаграма комунікації 
Послідовність затвердження заявки (метод review_request): HR-менеджер → 
POST /api/leaves/requests/{id}/review/ {decision: approved, comment: ...} →
_is_manager() перевірка ролі → статус заявки PENDING? → 
_assert_leave_within_limit() перевірка балансу → оновлення LeaveRequest 
(status=approved, approved_by, approved_at) → LeaveApprovalLog.create() →
_recalculate_for_request() перерахунок LeaveBalance → log_audit_event() →
Response з оновленою заявкою. 
Рисунок 2.21 – Діаграма послідовності: затвердження заявки на відпустку 
57 
ЧДТУ 262247.008 ПЗ 
2.5.4. Діаграма скінченного автомата 
Заявка на відпустку (LeaveRequest) проходить через чотири стани. 
Початковий стан при створенні — PENDING. Переходи між станами: 
– PENDING → APPROVED (guard: working_days ≤ available_days; дія:
approved_by = user, approved_at = now(), LeaveBalance.used_days +=
working_days);
– PENDING → REJECTED (дія: rejection_reason = comment);
– PENDING → CANCELLED (будь-який авторизований користувач, власна
ініціатива);
– APPROVED → CANCELLED (тільки Admin/HR; LeaveBalance.used_days
-= working_days).
При кожному переході стану в LeaveApprovalLog додається новий запис з 
action, actor та comment. LeaveBalance автоматично перераховується методом 
_recalculate_leave_balance(). 
Рисунок 2.22 – Діаграма скінченного автомату: стани заявки на відпустку 
58 
ЧДТУ 262247.008 ПЗ 
Рисунок 2.23 – Діаграма послідовності: автоматичне створення профілю при 
найманні 
59 
ЧДТУ 262247.008 ПЗ 
При переведенні кандидата на стадію HIRED (PATCH 
/api/recruitment/applications/{id}/ {stage: hired}) виконується транзакційний метод 
perform_update() → _get_or_create_employee_from_application(): 
– пошук User за email кандидата (User.objects.filter(email=...).first()).
– якщо User не існує → User.create() з email, first_name, last_name,
role=employee, set_unusable_password().
– Ensure_employee_profile(user) → EmployeeProfile.get_or_create().
– Оновлення EmployeeProfile: department та position з вакансії, hire_date =
today().
– EmploymentHistory.create() з нотаткою «Hired via recruitment application
#{id}».
– Application.hired_employee = profile, application.save().
– Log_audit_event(action='recruitment.application_hired').
60 
ЧДТУ 262247.008 ПЗ 
ВИСНОВКИ ДО ДРУГОГО РОЗДІЛУ 
 У другому розділі розроблено повну модель системи автоматизації HR-
процесів. Визначено словник предметної галузі з 14 основними сутностями. 
Побудовано діаграму прецедентів (11 UC для 3 акторів). Спроектовано логічну 
структуру системи у вигляді 4 Django-застосунків з 12 моделями та перевірними 
обмеженнями на рівні БД. Розроблено архітектурні діаграми: компонентів та 
розгортання. Змодельовано поведінку 5 ключових процесів системи, включаючи 
детальний алгоритм AI-парсингу резюме з 13 кроками. 
61 
ЧДТУ 262247.008 ПЗ 
РОЗДІЛ 3. РОЗРОБКА ТА ТЕСТУВАННЯ ПРОГРАМНОГО 
ЗАБЕЗПЕЧЕННЯ 
3.1. Розробка програмного комплексу 
3.1.1. Обґрунтування вибору засобів реалізації 
Вибір технологічного стеку здійснювався з урахуванням вимог до 
продуктивності, можливостей AI-інтеграції та специфіки задач автоматизації HR-
процесів. Під час аналізу альтернатив порівнювалися: мови програмування 
серверної частини (Python, Node.js, Java), фреймворки для побудови REST API 
(Django REST Framework, FastAPI, Express), реляційні СУБД (PostgreSQL, MySQL, 
SQLite), а також клієнтські бібліотеки для побудови SPA (React, Vue, Angular). 
Використані технології наведено в таблиці 3.1 [28]. 
Таблиця 3.1 
Технологічний стек системи 
Технологія Версія Призначення та обґрунтування вибору 
Мова серверної частини. Провідна екосистема для AI 
Python 3.11 
та обробки документів 
Веб-фреймворк. ORM, міграції, адмін-панель, 
Django 6.0.5 
вбудована безпека 
Django REST REST API: ModelViewSet, Serializer, Permission-класи, 
3.16.1 
Framework фільтрація 
JWT-автентифікація: access (60 хв) + refresh (7 днів) 
SimpleJWT 5.5.1 
токени 
Витяг тексту з PDF-резюме. Підтримка складних 
pypdf 6.1.0 
PDF-структур 
PostgreSQL-драйвер для Python. Підтримка async, пул 
psycopg[binary] 3.2.12 
з'єднань 
62 
ЧДТУ 26. 2247.008 ПЗ 
Продовження таблиці 3.1 
Технологія Версія Призначення та обґрунтування вибору 
Vite 8.0.4 Білдер: HMR < 50 мс, старт dev-сервера < 500 мс 
React Router Клієнтська маршрутизація: ProtectedRoute, 
7.15.1 
DOM StaffManagementRoute 
СУБД: CHECK constraints, індекси, транзакції, JSON-
PostgreSQL 16 
поля 
OpenRouter AI-інтерфейс для парсингу CV кандидатів (GPT-
— 
API сумісні моделі) 
Python 3.11 обрано як мову серверної частини завдяки розвиненій екосистемі 
бібліотек для машинного навчання та обробки документів, читабельному 
синтаксису та широкому застосуванню у задачах автоматизації. Django 6.0.5 надає 
вбудований ORM, систему міграцій, адмін-панель та засоби автентифікації, що 
суттєво скорочує обсяг рутинного коду. Django REST Framework забезпечує 
декларативне визначення серіалізаторів і представлень API, підтримку фільтрації 
та пагінації. 
На клієнтській стороні обрано React 19 з новим компілятором, що забезпечує 
автоматичну оптимізацію рендерингу без використання useMemo і useCallback. 
TypeScript забезпечує статичну типізацію, що запобігає цілому класу помилок під 
час розробки. Vite [31] використовується як інструмент збірки завдяки миттєвому 
старту та швидкому гарячому перезавантаженню модулів. 
3.1.2. Опис структурної (функціональної) схеми. 
Реляційна база даних PostgreSQL містить 15 таблиць, організованих у чотири 
логічні групи відповідно до Django-застосунків: accounts (облікові записи та аудит), 
employees (персонал), leaves (відпустки) та recruitment (рекрутинг). Кожна таблиця 
включає обмеження цілісності на рівні СУБД — CHECK constraints, UNIQUE 
constraints та зовнішні ключі з визначеною поведінкою при видаленні. 
63 
ЧДТУ 262247.008 ПЗ 
Логічна структура бази даних описується ER-моделлю, що відображає 
сутності системи та зв'язки між ними. Основною центральною сутністю є 
accounts_user — обліковий запис користувача, на якому базуються всі модулі 
системи через зовнішні ключі. Нижче наведено детальний опис кожної таблиці. 
Модуль accounts — облікові записи та аудит 
Модуль accounts реалізує аутентифікацію користувачів, управління ролями 
та ведення журналу аудиту. Містить дві таблиці: accounts_user та 
accounts_auditevent. 
Таблиця 3.2 
Схема таблиці accounts_user 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
Адреса ел. пошти — 
UNIQUE, NOT 
email EmailField(254) основний логін 
NULL 
(USERNAME_FIELD) 
Технічне поле AbstractUser 
username CharField(150) NOT NULL (не використовується для 
входу) 
first_name CharField(150) — Ім'я користувача 
last_name CharField(150) — Прізвище користувача 
Роль: admin / hr-manager / 
role CharField(20) choices 
employee 
DEFAULT Ознака активного облікового 
is_active BooleanField 
TRUE запису 
64 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.2 
DEFAULT Доступ до адмін-панелі 
is_staff BooleanField 
FALSE Django 
date_joined DateTimeField auto_now_add Дата та час реєстрації 
Дата останнього входу в 
last_login DateTimeField NULL 
систему 
Модель accounts_user розширює AbstractUser Django, замінюючи 
стандартний логін (username) на електронну адресу. Поле role визначає рівень 
доступу користувача і перевіряється класами дозволів на рівні кожного API-
ендпоінту. Таблиця є центральною — на неї посилаються всі інші таблиці через 
зовнішні ключі. 
Таблиця 3.3 
Схема таблиці accounts_auditevent 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → SET_NULL, Користувач, що виконав дію 
actor 
User NULL (може бути системним) 
Назва дії: login, role_changed, 
action CharField(120) NOT NULL 
leave_approved тощо 
Тип сутності: User, 
entity_type CharField(120) NOT NULL LeaveRequest, Application 
тощо 
65 
ЧДТУ 26247.008 ПЗ 
Продовження таблиці 3.3 
Ідентифікатор сутності, до 
entity_id CharField(64) NOT NULL 
якої відноситься дія 
Додаткові дані: нові/старі 
metadata JSONField DEFAULT {} 
значення полів, IP-адреса 
created_at DateTimeField auto_now_add Дата та час фіксації події 
Таблиця accounts_auditevent реалізує журнал аудиту системи. Кожна 
критична операція (зміна ролі, затвердження відпустки, найм кандидата) 
фіксується із зазначенням виконавця, типу та ідентифікатора сутності й довільними 
метаданими у форматі JSON. Індекси (action, created_at) та (entity_type, entity_id) 
оптимізують типові запити до журналу. 
Поле actor є зовнішнім ключем до таблиці accounts_user і допускає значення 
NULL — це дозволяє фіксувати системні події, що виконуються автоматично без 
участі конкретного користувача. Поле action містить короткий текстовий 
ідентифікатор виконаної дії (наприклад, leave_approved або candidate_hired), тоді як 
entity_type та entity_id разом однозначно визначають об'єкт, над яким виконано 
операцію. Поле metadata типу JSONField зберігає довільний контекст події — 
попередні значення полів, причини змін або додаткові параметри запиту — що 
забезпечує повноцінне відновлення історії без звернення до інших таблиць. Часова 
мітка created_at проставляється автоматично і не підлягає зміні, що гарантує 
цілісність хронології подій. 
Модуль employees — управління персоналом 
Модуль employees відповідає за зберігання даних про організаційну 
структуру підприємства та профілі співробітників. Містить чотири таблиці: 
employees_department, employees_position, employees_employeeprofile та 
employees_employmenthistory. 
66 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.4 
Схема таблиці employees_department 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
Повна назва відділу 
UNIQUE, NOT 
name CharField(150) (унікальна в межах 
NULL 
організації) 
UNIQUE, NOT Короткий код відділу: IT, 
code CharField(20) 
NULL HR, FIN тощо 
Опис функцій та обов'язків 
description TextField — 
відділу 
DEFAULT Ознака активного (чинного) 
is_active BooleanField 
TRUE відділу 
created_at DateTimeField auto_now_add Дата створення запису 
updated_at DateTimeField auto_now Дата останнього оновлення 
Таблиця accounts_auditevent реалізує журнал аудиту системи. Кожна 
критична операція (зміна ролі, затвердження відпустки, найм кандидата) 
фіксується із зазначенням виконавця, типу та ідентифікатора сутності й довільними 
метаданими у форматі JSON. Поле actor є зовнішнім ключем до таблиці 
accounts_user і допускає значення NULL — це дозволяє фіксувати системні події, 
що виконуються автоматично без участі конкретного користувача. Поле metadata 
типу JSONField зберігає довільний контекст події — попередні значення полів, 
причини змін або додаткові параметри запиту — що забезпечує повноцінне 
відновлення історії без звернення до інших таблиць. Часова мітка created_at 
проставляється автоматично і не підлягає зміні, що гарантує цілісність хронології 
подій. Структуру таблиці наведено у таблиці 3.5. 
67 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.5 
Схема таблиці employees_position 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
Назва посади: Software 
title CharField(150) NOT NULL 
Engineer, HR Manager тощо 
UNIQUE, NOT Уніфікований код посади: 
code CharField(30) 
NULL SWE, HRM, PM тощо 
Опис посадових обов'язків та 
description TextField — 
вимог 
DEFAULT Ознака актуальності посади 
is_active BooleanField 
TRUE в штатному розписі 
created_at DateTimeField auto_now_add Дата створення запису 
updated_at DateTimeField auto_now Дата останнього оновлення 
Таблиця employees_employeeprofile є центральною сутністю модуля 
employees і зберігає повну інформацію про кожного співробітника підприємства. 
Профіль пов'язаний із обліковим записом користувача відношенням «один до 
одного» через поле user, що унеможливлює існування співробітника без 
відповідного запису автентифікації. Унікальний табельний номер у форматі EMP-
XXXXX генерується автоматично при створенні профілю та слугує зовнішнім 
ідентифікатором співробітника у документообігу. 
Ієрархічна структура підпорядкування реалізована через рекурсивний 
зовнішній ключ manager, що посилається на той самий запис таблиці. Поля 
department та position використовують стратегію SET_NULL при видаленні 
пов'язаного запису — це дозволяє зберегти профіль співробітника навіть у разі 
реорганізації структури підприємства. Поле salary зберігає актуальний розмір 
68 
ЧДТУ 262247.008 ПЗ 
заробітної плати з перевіркою на невід'ємність, а поля created_at та updated_at 
заповнюються автоматично і забезпечують відстеження змін профілю. Структуру 
таблиці наведено у таблиці 3.6. 
Таблиця 3.6 
Схема таблиці employees_employeeprofile 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
Зв'язок 1:1 з 
user OneToOneField → User CASCADE обліковим 
записом 
Табельний номер 
у форматі EMP-
employee_number CharField(30) UNIQUE XXXXX 
(генерується 
автоматично) 
Відділ, до якого 
ForeignKey → SET_NULL, 
department відноситься 
Department NULL 
співробітник 
SET_NULL, Поточна посада 
position ForeignKey → Position 
NULL співробітника 
Безпосередній 
SET_NULL, керівник 
manager ForeignKey → self 
NULL (рекурсивний 
зв'язок) 
Тип зайнятості: 
employment_type CharField(20) choices full-time / part-time 
/ contract 
69 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.6 
Тип зайнятості: full-
employment_type CharField(20) choices time / part-time / 
contract 
Статус: active / 
employment_status CharField(20) choices probation / on-leave / 
terminated 
NOT Дата офіційного 
hire_date DateField 
NULL прийому на роботу 
Дата звільнення 
NULL, ≥ 
termination_date DateField (заповнюється при 
hire_date 
terminated) 
Дата народження (для 
birth_date DateField NULL розрахунку вікових 
пільг) 
Контактний номер 
phone CharField(30) — 
телефону 
Ім'я контактної особи 
emergency_contact_name CharField(150) — у надзвичайних 
ситуаціях 
Телефон контактної 
emergency_contact_phon
CharField(30) — особи у надзвичайних 
e 
ситуаціях 
Адреса проживання 
address CharField(255) — 
або реєстрації 
NULL, 
DecimalField(12,2 Розмір заробітної 
salary CHECK 
) плати 
≥ 0 
70 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.6 
auto_now Дата створення 
created_at DateTimeField 
_add профілю 
Дата останнього 
updated_at DateTimeField auto_now 
оновлення профілю 
Таблиця employees_employeeprofile є основною таблицею модуля персоналу 
та зберігає повну інформацію про кожного співробітника підприємства. Профіль 
пов'язаний із обліковим записом користувача відношенням «один до одного» через 
поле user, що унеможливлює існування співробітника без відповідного запису 
автентифікації. Рекурсивний зовнішній ключ manager дозволяє моделювати 
ієрархічну структуру підпорядкування будь-якої глибини без обмежень на 
кількість рівнів.  
Поле employee_number формується автоматично при створенні профілю у 
форматі EMP-XXXXX та слугує зовнішнім ідентифікатором співробітника у 
документообігу. Поля department та position використовують стратегію SET_NULL 
при видаленні пов'язаного запису — це дозволяє зберегти профіль співробітника 
навіть у разі реорганізації структури підприємства. На таблицю визначено складові 
індекси за полями department, employment_status та manager для прискорення 
типових фільтруючих запитів. Структуру таблиці наведено у таблиці 3.7. 
Таблиця 3.7 
Схема таблиці employees_employmenthistory 
Поле 
Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
71 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.7 
ForeignKey → 
employee CASCADE Профіль співробітника 
EmployeeProfile 
ForeignKey → SET_NULL, 
department Відділ на момент запису 
Department NULL 
ForeignKey → SET_NULL, 
position Посада на момент запису 
Position NULL 
ForeignKey → SET_NULL, 
manager Керівник на момент запису 
EmployeeProfile NULL 
Дата початку цього 
started_at DateField NOT NULL 
призначення 
NULL, ≥ Дата завершення (NULL = 
ended_at DateField 
started_at поточне призначення) 
Коментар: підстава 
note TextField — переміщення, підвищення 
тощо 
Дата фіксації запису в 
created_at DateTimeField auto_now_add 
системі 
Таблиця employees_employmenthistory фіксує всі переміщення співробітника 
між відділами та посадами, утворюючи повний аудит кар'єрного шляху. Кожен 
запис є незмінним — при зміні відділу або посади створюється новий запис, 
попередній зберігається. Запис із порожнім полем ended_at відповідає поточному 
призначенню. 
72 
ЧДТУ 262247.008 ПЗ
          Модуль leaves — управління відпустками 
Модуль leaves реалізує повний цикл управління відпустками: від визначення 
корпоративних полісів та відстеження балансу до обробки заявок і ведення 
журналу рішень. Містить чотири таблиці: leaves_leavepolicy, leaves_leavebalance, 
leaves_leaverequest та leaves_leaveapprovallog. 
Таблиця 3.8 
Схема таблиці leaves_leavepolicy 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
UNIQUE, Назва поліса: "Щорічна 
name CharField(150) 
NOT NULL відпустка 24 дні" тощо 
Тип: vacation / sick / 
leave_type CharField(20) choices unpaid / maternity / 
paternity / other 
Кількість днів відпустки 
annual_days PositiveIntegerField NOT NULL 
на рік за даним полісом 
Максимум 
невикористаних днів, що 
carryover_days PositiveIntegerField DEFAULT 0 
переносяться на 
наступний рік 
DEFAULT Чи потрібне затвердження 
requires_approval BooleanField 
TRUE керівником/HR 
created_at DateTimeField auto_now_add Дата створення запису 
Дата останнього 
updated_at DateTimeField auto_now 
оновлення 
73 
ЧДТУ 262247.008 ПЗ 
Таблиця leaves_leavebalance реалізує облік відпускних днів кожного 
співробітника в розрізі типу відпустки та розрахункового року. Унікальне 
обмеження за комбінацією полів employee, leave_type та year гарантує існування 
рівно одного запису балансу для кожної комбінації співробітника, типу відпустки і 
року, що унеможливлює дублювання даних. Поле total_days містить загальну 
кількість доступних днів на поточний рік з урахуванням перенесеного залишку з 
попереднього року відповідно до налаштувань політики відпусток. Поле used_days 
відображає фактично використані дні — тобто дні, що відповідають заявкам зі 
статусом approved, тоді як поле pending_days акумулює дні за заявками, що 
очікують на затвердження. Перерахунок балансу виконується автоматично при 
кожній зміні статусу заявки на відпустку, а часова мітка updated_at фіксує момент 
останнього оновлення запису. Структуру таблиці наведено у таблиці 3.9. 
Таблиця 3.9 
Схема таблиці leaves_leavebalance 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → 
employee CASCADE Профіль співробітника 
EmployeeProfile 
Тип відпустки (відповідає 
leave_type CharField(20) choices 
типам у leaves_leavepolicy) 
year PositiveIntegerField NOT NULL Розрахунковий рік балансу 
74 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.9 
Загальна кількість 
total_days DecimalField(6,2) CHECK ≥ 0 доступних днів на 
поточний рік 
Фактично використані дні 
used_days DecimalField(6,2) CHECK ≥ 0 
(статус approved) 
Дні у заявках зі статусом 
pending_days DecimalField(6,2) CHECK ≥ 0 
pending 
updated_at DateTimeField auto_now Дата перерахунку балансу 
На таблицю leaves_leavebalance визначено такі обмеження: 
UNIQUE(employee, leave_type, year) — гарантує існування рівно одного запису 
балансу для кожного типу відпустки на рік для кожного співробітника; CHECK 
used_days ≤ total_days — унеможливлює перевищення ліміту; CHECK total_days ≥ 
0, used_days ≥ 0, pending_days ≥ 0 — забороняють від'ємні значення.  
Сукупність цих обмежень забезпечує цілісність даних на рівні бази даних 
незалежно від логіки застосунку, що виключає виникнення некоректних станів 
балансу навіть у разі прямого звернення до бази даних. Баланс автоматично 
перераховується при кожній зміні статусу заявки, що забезпечує актуальність 
показників у реальному часі без необхідності ручного втручання. Часова мітка 
updated_at дозволяє відстежувати момент останнього перерахунку та 
використовується для діагностики у разі виявлення розбіжностей між фактичним 
станом заявок і записаним балансом. 
Таблиця 3.10 
Схема таблиці leaves_leaverequest 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
75 
ЧДТУ 26247.008 ПЗ 
Продовження таблиці 3.10 
Тип відпустки згідно з 
leave_type CharField(20) choices 
полісом 
Статус: pending / approved 
status CharField(20) choices 
/ rejected / cancelled 
start_date DateField NOT NULL Дата початку відпустки 
NOT NULL, Дата завершення 
end_date DateField 
≥ start_date відпустки 
Кількість робочих днів 
авто, CHECK 
working_days DecimalField(6,2) (без вихідних, 
> 0
авторозрахунок) 
Обґрунтування заявки від 
reason TextField — 
співробітника 
ForeignKey → SET_NULL, Користувач, що затвердив 
approved_by 
User NULL або відхилив заявку 
Дата та час прийняття 
approved_at DateTimeField NULL 
рішення 
Причина відхилення 
rejection_reason TextField — (заповнюється 
HR/адміном) 
created_at DateTimeField auto_now_add Дата подачі заявки 
Дата останньої зміни 
updated_at DateTimeField auto_now 
заявки 
Поле working_days розраховується автоматично на рівні серіалізатора Django 
REST Framework: із загального проміжку дат виключаються суботи та неділі.  
76 
ЧДТУ 262247.008 ПЗ 
Наявність CHECK > 0  на рівні СУБД виключає подачу заявок на нульову 
кількість робочих днів. Індекс (employee, status) прискорює фільтрацію заявок за 
співробітником та статусом, а індекс (start_date, end_date) — запити до календаря 
відпусток. 
Таблиця 3.11 
 Схема таблиці leaves_leaveapprovallog 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → Заявка, до якої відноситься 
leave_request CASCADE 
LeaveRequest запис журналу 
Дія: created / submitted / 
action CharField(30) choices approved / rejected / 
cancelled 
ForeignKey → SET_NULL, Виконавець дії (може бути 
actor 
User NULL системним тригером) 
Коментар: причина 
comment TextField — 
рішення, примітки HR тощо 
created_at DateTimeField auto_now_add Дата та час фіксації події 
Таблиця leaves_leaveapprovallog фіксує повний ланцюжок рішень по кожній 
заявці. Кожна зміна статусу заявки автоматично породжує запис у журналі — це 
унеможливлює несанкціоновані зміни та забезпечує прозорість процесу прийняття 
рішень. Журнал є незмінним: записи до нього лише додаються. 
Модуль recruitment — рекрутинг та підбір персоналу 
Модуль recruitment автоматизує повний цикл підбору персоналу: від 
публікації вакансії до найму кандидата. Містить п'ять таблиць: recruitment_vacancy, 
77 
ЧДТУ 262247.008 ПЗ 
recruitment_candidate, recruitment_application, recruitment_interview та 
recruitment_recruitmentnote. 
Таблиця 3.12 
Схема таблиці recruitment_vacancy 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
Назва вакансії: "Senior 
title CharField(150) NOT NULL 
Python Developer" тощо 
UNIQUE, Унікальний код вакансії: 
code CharField(30) 
NOT NULL VAC-2024-001 тощо 
ForeignKey → SET_NULL, Відділ, до якого відкрито 
department 
Department NULL вакансію 
ForeignKey → SET_NULL, Посада, що закривається 
position 
Position NULL вакансією 
Статус: draft / open / paused 
status CharField(20) choices 
/ closed / filled 
Місце роботи: місто або 
location CharField(120) — 
"Remote" 
Повний опис вакансії, 
description TextField — 
вимоги та умови 
NULL, Нижня межа зарплатної 
salary_from DecimalField(10,2) 
CHECK ≥ 0 вилки 
NULL, ≥ Верхня межа зарплатної 
salary_to DecimalField(10,2) 
salary_from вилки 
78 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.12 
Дата та час публікації 
opened_at DateTimeField NULL вакансії (при переході в 
open) 
Дата та час закриття 
closed_at DateTimeField NULL 
вакансії 
ForeignKey → SET_NULL, Користувач, що створив 
created_by 
User NULL вакансію 
created_at DateTimeField auto_now_add Дата створення запису 
updated_at DateTimeField auto_now Дата останнього оновлення 
Таблиця recruitment_candidate зберігає профіль кожного претендента, що 
звернувся до системи. Унікальне поле email слугує природним ідентифікатором 
кандидата та унеможливлює створення дублікатів при повторному зверненні. Поле 
source фіксує канал залучення кандидата — LinkedIn, job-портал, реферал, власний 
сайт або інше джерело — що дозволяє аналізувати ефективність різних каналів 
рекрутингу. Поля technologies та notes заповнюються автоматично модулем 
парсингу CV при завантаженні резюме у форматі PDF, а також можуть 
редагуватися рекрутером вручну. Структуру таблиці наведено у таблиці 3.13. 
Таблиця 3.13 
Схема таблиці recruitment_candidate 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
first_name CharField(100) NOT NULL Ім'я кандидата 
79 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.13 
last_name CharField(100) NOT NULL Прізвище кандидата 
Електронна пошта 
UNIQUE, 
email EmailField(254) (унікальний 
NOT NULL 
ідентифікатор кандидата) 
Контактний номер 
phone CharField(30) — 
телефону 
Джерело: linkedin / job-
source CharField(20) choices portal / referral / website / 
other 
Посилання на профіль 
linkedin_url URLField — 
LinkedIn 
Посилання на портфоліо 
portfolio_url URLField — 
або GitHub 
NULL, Загальний досвід роботи в 
experience_years DecimalField(4,1) 
CHECK ≥ 0 роках 
Очікуваний рівень 
expected_salary DecimalField(10,2) NULL 
заробітної плати 
Дата першого звернення 
created_at DateTimeField auto_now_add 
кандидата 
Дата останнього 
updated_at DateTimeField auto_now 
оновлення профілю 
Поточне місце роботи 
current_company CharField(120) — 
кандидата 
80 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.13 
current_position CharField(120) — Поточна посада кандидата 
Перелік технологій через 
technologies TextField — 
кому (витягується з CV) 
Загальні нотатки 
notes TextField — 
рекрутера щодо кандидата 
Таблиця recruitment_candidate зберігає єдиний профіль кандидата незалежно 
від кількості його звернень. Унікальність поля email гарантує відсутність 
дублікатів. Поля technologies, current_company, current_position та experience_years 
автоматично заповнюються AI-парсером при завантаженні PDF-резюме. 
Таблиця 3.14 
Схема таблиці recruitment_application 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → 
candidate CASCADE Профіль кандидата 
Candidate 
ForeignKey → Вакансія, на яку подається 
vacancy CASCADE 
Vacancy заявка 
Стадія: applied / screening / 
stage CharField(20) choices interview / test-task / offer / 
hired / rejected 
81 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці  3.14 
ForeignKey → SET_NULL, 
assigned_recruiter Відповідальний рекрутер 
User NULL 
NULL, 
Загальна оцінка кандидата 
score DecimalField(5,2) CHECK 
за підсумками відбору 
[0..100] 
OneToOneField Профіль співробітника 
hired_employee → NULL (заповнюється 
EmployeeProfile автоматично при hired) 
applied_at DateTimeField auto_now_add Дата та час подачі заявки 
Дата останнього 
updated_at DateTimeField auto_now 
оновлення заявки 
Посилання на збережений 
resume_url URLField — 
файл резюме 
Супровідний лист 
cover_letter TextField — 
кандидата 
На таблицю recruitment_application визначено обмеження UNIQUE(candidate, 
vacancy), що виключає подачу одним кандидатом двох заявок на одну й ту ж 
вакансію. При переведенні заявки до стадії hired система автоматично створює 
обліковий запис accounts_user, профіль employees_employeeprofile та перший запис 
в employees_employmenthistory. Поле hired_employee встановлює зворотній зв'язок 
між рекрутинговою заявкою та профілем новоствореного співробітника. 
82 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.15 
Схема таблиці recruitment_interview 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → Заявка кандидата, для якої 
application CASCADE 
Application проводиться співбесіда 
ForeignKey → SET_NULL, Інтерв'юер — 
interviewer 
User NULL співробітник компанії 
Тип: hr / tech / manager / 
interview_type CharField(20) choices 
final 
Статус: scheduled / 
status CharField(20) choices completed / cancelled / no-
show 
choices, Рекомендація: strong-hire / 
recommendation CharField(20) 
NULL hire / hold / reject 
Заплановані дата та час 
scheduled_at DateTimeField NOT NULL 
проведення 
Тривалість співбесіди у 
duration_minutes PositiveIntegerField DEFAULT 60 
хвилинах 
Детальний відгук 
feedback TextField — 
інтерв'юера за підсумками 
Дата створення запису 
created_at DateTimeField auto_now_add 
про співбесіду 
Дата останнього 
updated_at DateTimeField auto_now 
оновлення 
Таблиця recruitment_recruitmentnote забезпечує ведення внутрішніх нотаток 
рекрутерів та HR-менеджерів у межах конкретної заявки кандидата. Поле author 
використовує стратегію SET_NULL при видаленні користувача, що дозволяє 
83 
ЧДТУ 26247.008 ПЗ 
зберегти історію нотаток навіть після деактивації облікового запису автора. 
Часова мітка created_at проставляється автоматично і не підлягає зміні, що 
гарантує достовірність хронології коментарів у процесі рекрутингу. Структуру 
таблиці наведено у таблиці 3.16. 
Таблиця 3.16 
Схема таблиці recruitment_recruitmentnote 
Поле Тип даних Обмеження Призначення 
PRIMARY Автоінкрементний 
id BigAutoField 
KEY первинний ключ 
ForeignKey → Заявка, до якої відноситься 
application CASCADE 
Application нотатка 
ForeignKey → SET_NULL, Автор нотатки (рекрутер 
author 
User NULL або HR-менеджер) 
Зміст нотатки: 
note TextField NOT NULL спостереження, результати 
перевірок тощо 
Дата та час створення 
created_at DateTimeField auto_now_add 
нотатки 
Для оптимізації продуктивності бази даних визначено складові індекси за 
полями, що найчастіше використовуються у фільтруючих запитах. У таблиці 3.17 
наведено перелік індексів системи. 
84 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.17 
Індекси бази даних системи 
Таблиця Індекс (поля) Призначення 
Фільтрація журналу за типом 
accounts_auditevent (action, created_at) 
дії та часом 
(entity_type, Пошук всіх подій, пов'язаних з 
accounts_auditevent 
entity_id) конкретною сутністю 
Фільтрація персоналу за 
employees_employeeprofile (department) 
відділом 
Вибірка активних/звільнених 
employees_employeeprofile (employment_status) 
співробітників 
Побудова дерева 
employees_employeeprofile (manager) 
підпорядкування 
Вибірка заявок конкретного 
leaves_leaverequest (employee, status) 
співробітника за статусом 
(start_date, Запити до календаря відпусток 
leaves_leaverequest 
end_date) за діапазоном дат 
Формування Kanban-дошки за 
recruitment_application (stage) 
стадіями відбору 
Унікальний індекс для 
recruitment_application (candidate, vacancy) 
UNIQUE constraint 
3.1.3. Опис логічної схеми системи 
Серверна частина реалізована у вигляді RESTful API на базі Django REST 
Framework. Кожен застосунок має стандартну структуру: models.py → serializers.py 
→ views.py → urls.py → permissions.py (для accounts).
85 
ЧДТУ 262247.008 ПЗ 
Система рольового розмежування доступу реалізована через Permission-
класи (accounts/permissions.py): 
class HasRole(BasePermission):
allowed_roles: tuple[str, ...] = ()
def has_permission(self, request, view):
user = request.user
return bool(
user and user.is_authenticated
and getattr(user, 'role', None) in self.allowed_roles
)
class IsAdminRole(HasRole):
allowed_roles = ('admin',)
class IsAdminOrHRManager(HasRole): 
allowed_roles = ('admin', 'hr-manager') 
Рисунок 3.2 – Permission-класи системи рольового доступу 
(accounts/permissions.py) 
86 
ЧДТУ 262247.008 ПЗ 
Система аудиту (accounts/audit.py) протоколює всі критичні операції зі 
збереженням у таблиці AuditEvent. Функція log_audit_event() приймає: actor 
(користувач), action (ідентифікатор події), entity_type та entity_id (тип і ID сутності), 
metadata (dict з додатковими даними). Помилки запису до БД перехоплюються та 
не блокують основний потік виконання. 
Рисунок 3.3 – Функція логування аудит-подій (accounts/audit.py) 
Бізнес-логіка управління відпустками (leaves/views.py) реалізує алгоритм 
підрахунку робочих днів через ітерацію по кожному дню від start_date до end_date 
з перевіркою weekday() < 5 (понеділок=0, п'ятниця=4). 
87 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.4 – Алгоритм підрахунку робочих днів (leaves/views.py) 
Перерахунок балансу відпусток (метод _recalculate_leave_balance) 
виконується після кожної зміни статусу заявки. Метод отримує кількість 
затверджених та очікуваних днів через агрегацію Django ORM (Sum), після чого 
оновлює відповідний запис LeaveBalance через save(update_fields=[...]). 
Рисунок 3.5 – Автоматичний перерахунок балансу відпусток (leaves/views.py) 
88 
ЧДТУ 262247.008 ПЗ 
3.1.4. Розробка бази даних. 
AI-модуль є ключовою інноваційною складовою розробленої системи. 
Реалізований у файлі recruitment/cv_parsing.py та містить 5 основних функцій: 
extract_pdf_text(), parse_cv_with_openrouter(), fetch_openrouter_free_model_ids(), 
fallback_parse_cv_text() та допоміжні функції нормалізації даних. 
Витяг тексту з PDF 
Функція extract_pdf_text() реалізує витяг тексту з PDF-документу з 
підтримкою двох бібліотек через динамічний імпорт. Спочатку робиться спроба 
імпортувати pypdf, при невдачі — PyPDF2. Текст витягується посторінково, 
порожні сторінки фільтруються, результат конкатенується з подвійними 
переносами рядків. 
Рисунок 3.6 – Схема витягу тексту з PDF (cv_parsing.py) 
89 
ЧДТУ 262247.008 ПЗ 
Запит до OpenRouter API 
Функція parse_cv_with_openrouter() формує HTTP-запит до OpenRouter API з 
system prompt та текстом резюме. Параметр temperature=0 гарантує 
детермінованість відповіді. Параметр response_format: {"type": "json_object"} 
активує режим структурованого виводу — модель гарантовано повертає валідний 
JSON. Ліміт cv_text[:15000] обмежує розмір запиту для сумісності з 
безкоштовними моделями. 
Рисунок 3.7 – Схема запиту до OpenRouter API (cv_parsing.py) 
90 
ЧДТУ 262247.008 ПЗ 
Автоматичний вибір безкоштовних моделей 
Функція fetch_openrouter_free_model_ids() отримує список безкоштовних 
моделей через OpenRouter API та кешує результат на 15 хвилин (ttl_seconds=900). 
Запит до /api/v1/models/user фільтрує моделі з суфіксом ':free'. Метод 
_resolve_openrouter_models() формує пріоритетний список: спочатку явно задані у 
.env, потім openrouter/free, потім до 40 безкоштовних виявлених моделей. 
Рисунок 3.8 – Отримання та кешування безкоштовних моделей (cv_parsing.py) 
91 
ЧДТУ 262247.008 ПЗ 
Механізм exponential backoff 
При перевищенні ліміту запитів (HTTP 429) реалізований алгоритм 
exponential backoff. [12] Для моделі 'openrouter/free' виконується до 3 спроб із 
затримками 1.2, 2.4 та 3.6 секунди. Функція _is_retryable_ai_error() визначає 
тимчасові помилки: '(429)' у тексті або 'rate-limit'/'rate limited' у повідомленні. 
Постійні помилки (404, 401) не повторюються. 
Рисунок 3.9 – Алгоритм exponential backoff при rate limiting (recruitment/views.py) 
92 
ЧДТУ 262247.008 ПЗ 
Regex-резервний парсер 
Функція fallback_parse_cv_text() активується при недоступності AI. Функція 
_email_from_text() реалізує пошук email-адрес через regex, включаючи обфусковані 
формати 'john [at] example [dot] com'. Функція _skills_from_text() шукає 33 патерни 
[25] [27]технологій у тексті (HTML, CSS, JavaScript, TypeScript, React, Python,
Django, PostgreSQL, Docker, Kubernetes, AWS, Git та ін.) та повертає список 
знайдених навичок (до 30). Функція _name_from_text() аналізує перші 20 рядків 
резюме, виключаючи стоп-слова. 
Рисунок 3.10 – Regex-парсер email з підтримкою обфускованих адрес 
(cv_parsing.py) 
93 
ЧДТУ 262247.008 ПЗ 
Нормалізація та збереження даних 
Після парсингу (AI або regex) виконується нормалізація даних. При 
відсутності email генерується placeholder-адреса у форматі candidate-
{token}@placeholder.local. Збереження виконується через get_or_create за 
унікальним email кандидата. При повторному завантаженні резюме наявного 
кандидата технології об'єднуються (merging) без дублювань. 
Рисунок 3.11 – Нормалізація даних та збереження Candidate (recruitment/views.py) 
3.1.5. Розробка інтерфейсу користувача 
Клієнтська частина реалізована як SPA на базі React 19 + TypeScript. 
Структура: src/app/router/ (маршрутизація), src/pages/ (8 функціональних модулів), 
94 
ЧДТУ 262247.008 ПЗ 
src/store/ (authStore), src/utils/ (apiClient, formatDate, calculateDays, errors), src/types/ 
(TypeScript-типи). 
Модуль управління станом автентифікації (authStore.ts) реалізований як 
власний pub/sub стор без зовнішніх залежностей. Стан authState зберігає user, role 
та isAuthenticated. Функції setAuthUser() та clearAuthUser() оновлюють стан і 
нотифікують всіх передплатників через listeners. Персистентність забезпечується 
через localStorage. 
Рисунок 3.12 – Pub/sub стор автентифікації (store/authStore.ts) 
HTTP-клієнт (utils/apiClient.ts) забезпечує авторизовані запити з 
автоматичним refresh-механізмом та дедуплікацією паралельних запитів на 
оновлення токена через singleton-проміс refreshPromise. 
95 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.13 – Механізм автоматичного оновлення JWT-токена (utils/apiClient.ts) 
Функція підрахунку робочих днів (utils/calculateDays.ts) реалізована на 
фронтенді для попереднього розрахунку перед відправкою заявки. Алгоритм ітерує 
по кожному дню від startDate до endDate та рахує дні з weekday !== 0 (не неділя) та 
weekday !== 6 (не субота). 
Рисунок 3.14 – Функція підрахунку робочих днів (utils/calculateDays.ts) 
96 
ЧДТУ 262247.008 ПЗ 
TypeScript-тип User (src/types/user.ts) визначає інтерфейс з полями: id 
(number), username, firstName, lastName, email (string), role (UserRole: 'admin' | 'hr-
manager' | 'employee'), department, position (опціональні рядки), isActive (boolean), 
createdAt (опціональний рядок). 
Рисунок 3.15 – TypeScript-тип User (types/user.ts) 
3.1.6. Опис розробки програмних компонентів 
Логічна схема функціонування системи побудована на основі React-
компонент, що взаємодіють з REST API через apiClient. Маршрутизація реалізована 
через AppRouter.tsx: ProtectedRoute перевіряє isAuthenticated зі стану authStore і при 
false виконує redirect на /login. StaffManagementRoute перевіряє role ∈ {admin, hr-
97 
ЧДТУ 262247.008 ПЗ 
manager} і при false виконує redirect на /dashboard. Кожна сторінка модуля містить 
файл model/*.api.ts з функціями для HTTP-запитів та компоненти для відображення 
даних. 
Рисунок 3.16 – Логічна схема React-застосунку 
98 
ЧДТУ 262247.008 ПЗ 
Розробка інтерфейсу користувача 
Розробка клієнтської частини системи автоматизації HR-процесів 
здійснювалась відповідно до принципів компонентного підходу та розмежування 
відповідальності між шарами застосунку. Інтерфейс реалізовано як 
односторінковий застосунок (SPA) на базі React 19 з TypeScript, що забезпечує 
реактивне оновлення DOM без перезавантаження сторінки. 
Стилізацію виконано засобами чистого CSS без використання зовнішніх UI-
фреймворків (Tailwind, Material UI, styled-components). Така архітектура забезпечує 
повний контроль над зовнішнім виглядом, мінімальний розмір бандлу та 
відсутність залежностей від зовнішніх систем дизайну. Кожна сторінка та 
компонент мають власний ізольований CSS-файл, що унеможливлює конфлікти 
стилів. 
Архітектура стилів 
Система найменування CSS-класів побудована за методологією BEM (Block–
Element–Modifier) [53]. Відповідно до цього підходу, кожен клас відображає 
належність елемента до блоку, його роль усередині блоку або варіант 
відображення. Наприклад: .dashboard-page__header для заголовка сторінки 
Dashboard, .leaves-form__field для поля форми заявки на відпустку, .candidate-card-
-rejected для картки відхиленого кандидата. Такий підхід усуває неоднозначність у
стилізації та спрощує супровід коду. 
Для розкладки елементів сторінок використовуються CSS Grid та Flexbox. 
Grid застосовується для побудови багатоколонкових макетів — сітка статистичних 
карток Dashboard, Kanban-дошка рекрутингу. Flexbox використовується для 
вирівнювання елементів усередині рядків — навігаційна панель, рядки таблиць, 
заголовки секцій. 
Модальні вікна реалізовано через CSS-властивість position: fixed з 
напівпрозорим фоновим шаром (backdrop), що перекриває основний контент 
сторінки. Анімація появи модального вікна забезпечується CSS-переходами opacity 
та transform, без використання JavaScript-бібліотек анімацій. 
99 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.18 
Структура CSS-файлів клієнтської частини 
Файл / директорія Призначення 
Глобальне скидання браузерних стилів (box-
styles/reset.css 
sizing, margin, padding) 
Глобальні стилі: CSS-змінні, шрифти, базові 
index.css 
елементи 
pages/auth/Login.css Стилі сторінки входу та showcase-панелі 
pages/dashboard/Dashboard.css Сітка карток, календар, стрічка подій 
Таблиця персоналу, фільтри, inline-форма 
pages/employees/Employees.css 
редагування 
Таблиця заявок, панель балансу, форма нової 
pages/leaves/Leaves.css 
заявки 
Kanban-дошка: колонки, картки кандидатів, 
pages/recruitment/Recruitment.css 
drag-індикатори 
Список вакансій, статус-бейджі, форма 
pages/vacancies/Vacancies.css 
вакансії 
Таблиця користувачів, role-бейджі, форма 
pages/usersRoles/UsersRoles.css 
створення 
Картка профілю, форма редагування, секція 
pages/profile/MyProfile.css 
зміни пароля 
Стилі перевикористовуваних компонентів 
components/ui/ 
Button, Input 
100 
ЧДТУ 262247.008 ПЗ 
Маршрутизація та захист сторінок 
Клієнтська маршрутизація реалізована засобами React Router DOM 7 [32]. 
Конфігурацію маршрутів централізовано винесено в компонент AppRouter, що 
спрощує управління доступом та додавання нових сторінок. Шляхи визначено у 
файлі paths.ts як константи, що виключає помилки через опечатки у рядкових 
значеннях. 
Захист маршрутів забезпечується двома компонентами вищого порядку. 
Компонент ProtectedRoute перехоплює запити до захищених сторінок та 
перенаправляє неавтентифікованих користувачів на сторінку входу /login. 
Компонент StaffManagementRoute додатково перевіряє роль користувача та 
обмежує доступ до адміністративних сторінок лише для ролей admin та hr-manager, 
перенаправляючи звичайних співробітників на /dashboard. Перелік маршрутів 
системи наведено в таблиці 3.19. 
Таблиця 3.19 
Маршрути клієнтської частини системи 
Шлях Компонент Захист Призначення 
Аутентифікація 
/login pages/auth/Login.tsx Публічний користувача в 
системі 
Активація нового 
/activate pages/auth/ActivateAccount.tsx Публічний 
облікового запису 
Головна панель зі 
/dashboard pages/dashboard/Dashboard.tsx Authenticated статистикою та 
календарем 
/profile pages/profile/MyProfile.tsx Authenticated Особистий профіль 
Управління заявками 
/leaves pages/leaves/index.tsx Authenticated 
на відпустку 
101 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.19 
Шлях Компонент Захист Призначення 
Перегляд та 
/employees pages/employees/index.tsx StaffOnly 
редагування персоналу 
Управління відкритими 
/vacancies pages/vacancies/index.tsx StaffOnly 
вакансіями 
Kanban-дошка підбору 
/candidates pages/recruitment/index.tsx StaffOnly 
персоналу 
Управління обліковими 
/users-roles pages/usersRoles/index.tsx StaffOnly 
записами та ролями 
Сторінки аутентифікації 
Сторінка входу (/login) розділена на дві частини. Ліва частина — showcase-
панель — відображає назву системи, короткий опис можливостей та перелік 
ключових функцій у вигляді ілюстративних блоків. Права частина містить форму 
входу з полями email та password, кнопкою підтвердження і обробкою помилок 
аутентифікації. Такий двоколонковий макет забезпечує ознайомлення нових 
користувачів з функціональністю системи безпосередньо на стартовій сторінці. 
Форма входу виконує валідацію полів на стороні клієнта перед відправкою 
запиту: перевіряється формат електронної пошти та непустота пароля. При помилці 
аутентифікації відображається повідомлення з розшифровкою причини — невірні 
облікові дані або неактивний обліковий запис. Успішна аутентифікація зберігає 
JWT-токени та дані користувача в authStore і перенаправляє на /dashboard. 
Сторінка активації облікового запису (/activate) призначена для першого 
входу щойно найнятого співробітника. Форма приймає тимчасовий токен та дає 
можливість встановити постійний пароль. Цей процес запускається автоматично 
при переведенні кандидата у статус hired у модулі рекрутингу. 
102 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.17 – Cторінка аутентифікації 
Головна панель Dashboard 
Сторінка Dashboard (/dashboard) є стартовою сторінкою після входу та 
відображає агреговану інформацію про поточний стан HR-процесів організації. 
Сторінка складається з трьох функціональних зон: статистичні картки, календар 
відпусток та стрічка подій. 
Блок статистичних карток містить чотири інформаційні одиниці: загальна 
кількість активних співробітників, кількість відділів організації, кількість 
відкритих вакансій та кількість активних кандидатів у воронці підбору. Кожна 
картка супроводжується піктограмою та відсотковою зміною відносно 
попереднього розрахункового періоду. Для фільтрації статистики доступні три 
режими: поточний місяць, попередній місяць та квартал. 
Календар відпусток відображає поточний місяць у вигляді сітки тижнів. Дні 
з активними відпустками виділені кольором відповідно до типу відпустки, що 
дозволяє HR-менеджеру візуально оцінити навантаження на персонал за будь-який 
тиждень. Навігація між місяцями здійснюється кнопками без перезавантаження 
сторінки. 
Стрічка останніх подій (activity feed) відображає хронологічний перелік дій у 
системі: подачу заявок на відпустку, зміни статусу кандидатів, найм нових 
співробітників. Кожна подія містить мітку часу, іконку типу та короткий опис. 
103 
ЧДТУ 262247.008 ПЗ 
Глобальний рядок пошуку у верхній частині сторінки здійснює одночасний пошук 
по всіх модулях системи — профілях співробітників, заявках на відпустку, 
кандидатах та вакансіях — і відображає результати у групованому вигляді. 
Рисунок 3.18 – Головна сторінка Dashboard системи 
Сторінка управління персоналом 
Сторінка персоналу (/employees) доступна лише для ролей admin та hr-
manager. Основним елементом є таблиця співробітників з пагінацією, яка 
відображає табельний номер, повне ім'я, відділ, посаду, тип та статус зайнятості. 
Над таблицею розміщено панель фільтрів: пошук за ім'ям або email, вибір відділу, 
посади та статусу зайнятості. Поєднання фільтрів відбувається через логічне AND 
— відображаються лише записи, що відповідають усім вибраним критеріям 
одночасно. 
Для перегляду деталей співробітника передбачено модальне вікно, що 
відкривається при натисканні на рядок таблиці. Вікно містить повну інформацію 
профілю: контактні дані, адресу, дату народження, дату найму, розмір заробітної 
плати, контактну особу на випадок надзвичайних ситуацій. Для ролей admin та hr-
manager доступне inline-редагування всіх полів безпосередньо у модальному вікні 
без переходу на окрему сторінку редагування. 
104 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.19 – Сторінка управління персоналом 
Сторінка рекрутингу та Kanban-дошка 
Сторінка кандидатів (/candidates) реалізована як Kanban-дошка, що 
відображає повну воронку підбору персоналу. Дошка містить сім стадій відбору, 
розташованих у горизонтальну послідовність колонок: Applied (нові заявки), 
Screening (первинний відбір), Interview (співбесіда), Test Task (тестове завдання), 
Offer (офер), Hired (найнятий) та Rejected (відхилений). Кожна колонка відображає 
кількість кандидатів у заголовку та прокручується незалежно від інших за 
наявності великої кількості карток. 
Картка кандидата містить ім'я, очікуваний рівень заробітної плати, кількість 
років досвіду, прив'язану вакансію та дату подачі заявки. При натисканні на картку 
відкривається модальне вікно з повним профілем кандидата: контактні дані, 
поточне місце роботи, перелік технологій, посилання на LinkedIn та портфоліо, а 
також хронологія проведених співбесід із відгуками інтерв'юерів. 
У модальному вікні кандидата розміщено форму завантаження PDF-резюме 
для автоматичного парсингу за допомогою AI. Після завантаження файлу система 
надсилає запит на ендпоінт /api/recruitment/cv-parse/, бекенд витягує текст через 
pypdf, передає до OpenRouter API та повертає структурований JSON з даними 
кандидата. Результат автоматично заповнює поля профілю — ім'я, email, телефон, 
105 
ЧДТУ 262247.008 ПЗ 
досвід, список технологій, поточне місце роботи. HR-менеджер може 
відредагувати автоматично заповнені дані перед збереженням. 
Переміщення кандидата між стадіями здійснюється через випадаючий 
список у модальному вікні. При переведенні до стадії Hired система ініціює 
автоматичний процес онбордингу: створюється обліковий запис користувача, 
профіль співробітника та перший запис в історії призначень, після чого на 
електронну адресу надсилається лист з посиланням для активації. Нижня секція 
дошки відображає окремими горизонтальними списками найнятих та відхилених 
кандидатів. 
Рисунок 3.20 – Перша частина Kanban-дошки рекрутингу 
106 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.21 – Друга частина Kanban-дошки рекрутингу 
Сторінка управління відпустками 
Сторінка відпусток (/leaves) відрізняється за функціональністю залежно від 
ролі користувача. Для звичайного співробітника відображаються лише власні 
заявки та залишок балансу. Для HR-менеджера та адміністратора — заявки всього 
персоналу з можливістю фільтрації за відділом, типом відпустки та статусом. 
Верхня частина сторінки містить панель балансів — рядок карток для 
кожного типу відпустки (щорічна, лікарняна, без збереження заробітку, декретна). 
Кожна картка відображає три показники: total (загальний ліміт на рік), used 
(використано), pending (у заявках, що очікують затвердження). Дані оновлюються 
в реальному часі при зміні статусу будь-якої заявки. 
Основний елемент сторінки — таблиця заявок з такими стовпцями: 
співробітник, тип відпустки, дати початку та завершення, кількість робочих днів, 
статус та дата подачі. Рядки зі статусом pending виділяються кольором для 
привернення уваги HR-менеджера. Панель фільтрів дозволяє комбінувати фільтр 
за статусом (pending / approved / rejected / cancelled) та за типом відпустки. 
Кнопка "Подати заявку" відкриває модальне вікно з формою. Форма містить 
поля: тип відпустки (список з доступними полісами), дати початку та завершення, 
необов'язкове поле причини. Під час вибору дат автоматично підраховується 
107 
ЧДТУ 262247.008 ПЗ 
кількість робочих днів з виключенням вихідних та перевіряється достатність 
залишку балансу — у разі перевищення ліміту кнопка збереження блокується і 
відображається попередження. 
Для кожної заявки зі статусом pending HR-менеджер та адміністратор бачать 
кнопки "Затвердити" та "Відхилити". При відхиленні відкривається додаткове поле 
для введення причини, яка буде відображена заявнику. Кожен із співробітників 
може скасувати власну заявку у статусі pending за допомогою кнопки "Скасувати", 
що переводить заявку до статусу cancelled і повертає pending-дні у баланс. 
Рисунок 3.22 –Перша частина сторінки управління відпустками 
108 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.23 –Друга частина сторінки управління відпустками 
Сторінка управління вакансіями 
Сторінка вакансій (/vacancies) призначена для ведення реєстру відкритих, 
призупинених та закритих вакансій організації. Список вакансій відображає назву, 
унікальний код, відділ, посаду, зарплатну вилку та поточний статус. Статус вакансії 
позначається кольоровим бейджем: зелений для open, жовтий для paused, сірий для 
draft, червоний для closed та filled. 
Форма створення та редагування вакансії відкривається у модальному вікні. 
Обов'язкові поля: назва, код, статус. Необов'язкові: відділ, посада (вибір зі списку 
наявних), місце роботи, зарплатна вилка від/до, повний текст опису. Система 
перевіряє, що значення salary_to не було меншим за salary_from на рівні валідатора 
серіалізатора Django REST Framework та повертає зрозуміле повідомлення 
помилки у разі порушення. 
109 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.24 – Сторінка управління відпустками 
Сторінка управління користувачами та ролями 
Сторінка користувачів (/users-roles) доступна виключно для ролі admin та hr-
manager. Таблиця відображає всіх зареєстрованих користувачів системи з їх email-
адресами, повним ім'ям, поточною роллю та статусом активності. Роль та 
активність кожного облікового запису можна змінити безпосередньо у таблиці 
через випадаючі списки без переходу на окрему сторінку. 
Форма створення нового користувача генерує обліковий запис із тимчасовим 
паролем та надсилає на вказану email-адресу посилання для активації. 
Адміністратор призначає роль при створенні. Деактивація облікового запису 
(is_active = false) негайно анулює всі активні JWT-токени цього користувача, 
позбавляючи його доступу до системи без видалення даних. 
110 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.25 – Сторінка управління ролями та користувачами 
Сторінка особистого профілю 
Сторінка профілю (/profile) доступна всім аутентифікованим користувачам. 
Вона поділена на дві секції: редагування персональних даних та зміна пароля. 
Секція персональних даних дозволяє оновити ім'я, прізвище, email та номер 
телефону. Зміни відправляються методом PATCH на ендпоінт /api/accounts/me/, що 
оновлює лише передані поля без перезапису незмінених. Аватар профілю 
зберігається як base64-рядок у localStorage та відображається у навігаційній панелі. 
Секція зміни пароля містить три поля: поточний пароль, новий пароль та 
підтвердження нового пароля. Клієнтська валідація перевіряє збіг нового пароля та 
підтвердження ще до відправки запиту. Серверна валідація додатково перевіряє 
відповідність поточного пароля та вимоги до складності нового (мінімум 8 
символів, заборона на паролі, схожі з email). 
111 
ЧДТУ 262247.008 ПЗ 
Рисунок 3.26 – Сторінка особистого профілю 
Управління станом застосунку 
Замість глобального сховища (Redux, Zustand, Context API) у застосунку 
реалізовано мінімалістичний pub/sub-стор authStore для управління станом 
аутентифікації. Стор зберігає поточного користувача, його роль та ознаку 
аутентифікованості. Компоненти, що залежать від стану аутентифікації, 
підписуються на оновлення через функцію subscribeAuth і автоматично 
перерендерюються при зміні стану. 
Стан кожної окремої сторінки керується локальним useState всередині 
відповідного функціонального компонента. Такий підхід виключає надмірну 
складність глобального сховища для ізольованих даних сторінок та зменшує 
кількість перерендерів несуміжних компонентів. Запити до API здійснюються 
112 
ЧДТУ 262247.008 ПЗ 
через централізований клієнт apiClient, що автоматично підставляє Bearer-токен, 
обробляє 40 1-помилки та здійснює автоматичний рефреш токена. 
Таблиця 3.20 
Компоненти інтерфейсу та їх характеристики 
Сторінка / Роль Ключові UI-
API-ендпоінти 
компонент доступу елементи 
Двоколонковий 
Login Публічний макет, showcase, /api/accounts/login/ 
форма входу 
Статкартки, 
календар, 
/api/employees/, /api/leaves/, 
Dashboard Всі activity feed, 
/api/recruitment/ 
глобальний 
пошук 
Таблиця, 
admin, hr- мульти-фільтри, 
Employees /api/employees/profiles/ 
manager модальне вікно 
профілю 
Всі Баланс-картки, 
/api/leaves/requests/, 
Leaves (фільтрація таблиця заявок, 
/api/leaves/balances/ 
за роллю) форма подачі 
Канбан-дошка, 
картки, AI-
Candidates admin, hr- /api/recruitment/candidates/, 
парсинг PDF, 
(Kanban) manager /api/recruitment/cv-parse/ 
форма 
переміщення 
113 
ЧДТУ 262247.008 ПЗ 
Продовження таблиці 3.20 
Сторінка / Роль Ключові UI-
API-ендпоінти 
компонент доступу елементи 
Таблиця, inline-
Users & admin, hr-
зміна ролі, /api/accounts/users/ 
Roles manager 
форма створення 
Форма 
редагування 
Profile Всі /api/accounts/me/ 
даних, секція 
зміни пароля 
Таким чином, клієнтська частина системи реалізує всі визначені 
функціональні вимоги: розмежування доступу за роллю, реактивне оновлення 
даних, AI-асистований ввід даних кандидатів та зручний інтерфейс для всіх 
категорій користувачів системи. 
3.2. Тестування системи 
Тестування розробленої системи проводилось на чотирьох рівнях [39] [50] 
[51]: модульному, інтеграційному, системному та приймальному. Всього виконано 
52 тест-кейси, з яких 43 автоматизовані за допомогою Django TestCase та Django 
REST Framework APITestCase [54]. Тестове середовище використовує in-memory 
SQLite базу даних та бібліотеку unittest.mock для ізоляції зовнішніх залежностей. 
3.2.1. Модульне тестування 
Модульне тестування охоплює ізольовані одиниці коду без залежності від 
бази даних та зовнішніх сервісів [26]. Тест-кейси для функції 
_calculate_working_days() наведено в таблиці 3.21. 
114 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.21 
Тест-кейси модульного тестування підрахунку робочих днів 
№ start_date end_date Очікуваний результат Статус 
1 2026-01-06 (Пн) 2026-01-10 (Пт) 5 днів PASS 
2 2026-01-04 (Сб) 2026-01-05 (Нд) 0 днів PASS 
3 2026-01-06 (Пн) 2026-01-06 (Пн) 1 день PASS 
4 2026-01-10 2026-01-06 0 (end < start) PASS 
5 2026-01-06 2026-01-12 5 (Сб, Нд пропуск) PASS 
Код модульних тестів функції calculate_work_day() наведено на рисунку 3.1. 
Рисунок 3.27 – Код модульних тестів _calculate_working_days() (TC-01 – TC-05) 
115 
ЧДТУ 262247.008 ПЗ 
Код модульних тестів AI-парсингу (TC-AI-01-0 5) наведено на рисунку 3.2. 
Рисунок 3.28 – Код модульних тестів AI-парсингу резюме (TC-AI-01, 02, 04, 05) 
116 
ЧДТУ 262247.008 ПЗ 
Тест-кейси для AI-парсингу (з mock OpenRouter API): 
– TC-AI-01: Валідний JSON з усіма полями → всі поля збережені коректно
— PASS;
– TC-AI-02: JSON з markdown-обгорткою (```json ... ```) → 
_extract_json_from_model_output() коректно вилучає об'єкт — PASS;
– TC-AI-03: HTTP 429 → retry із затримкою, третя спроба успішна — PASS;
– TC-AI-04: Всі моделі повертають помилку → fallback_parse_cv_text()
активується — PASS;
– TC-AI-05: skills > 30 елементів → _normalize_skills() обрізає до 30 —
PASS.
Тест TC-AI-03 (exponential backoff при HTTP 429) [12] реалізується окремо 
через складніший mock-сценарій із двома послідовними помилками перед 
успішною відповіддю. Код тесту наведено на рисунку 3.29. 
Рисунок 3.29 – Код тесту TC-AI-03 — exponential backoff при HTTP 429 
117 
ЧДТУ 262247.008 ПЗ 
Аналіз результатів модульного тестування. Всі 10  тест-кейсів отримали 
статус PASS. Алгоритм підрахунку робочих днів коректно обробляє граничні 
випадки: порожній діапазон (TC-0 4), однодень (TC-0 3), тиждень із вихідними (TC-
05). AI-модуль повністю відповідає специфікації: 
_extract_json_from_model_output() обробляє обидва формати JSON, механізм 
exponential backoff [12] виконує рівно дві затримки (mock_sleep.call_count == 2) 
перед третьою успішною спробою, а _normalize_skills() гарантовано обрізає масив 
до 30  елементів незалежно від регістру та дедуплікує значення. 
3.2.2. Інтеграційне тестування 
Інтеграційне тестування перевіряє взаємодію між компонентами: REST API, 
бізнес-логікою, ORM та базою даних. Використано Django REST Framework 
APITestCase[54] [55] з in-memory SQLite. Код тестів автентифікації та рольового 
захисту ендпоінтів (INT-01, INT-02) наведено на рисунку 3.4. 
Рисунок 3.30 – Код інтеграційних тестів автентифікації та захисту ендпоінтів 
(INT-01, INT-02) 
118 
ЧДТУ 262247.008 ПЗ 
Код інтеграційних тестів циклу відпустки (INT-03, INT-0 4) наведено на 
рисунку 3.5. 
Рисунок 3.31 – Код інтеграційних тестів циклу відпустки (INT-03, INT-04) 
119 
ЧДТУ 262247.008 ПЗ 
Протестовані сценарії: 
– INT-01: Повний цикл автентифікації. POST /login/ → {access, refresh, user}
→ авторизований GET /me/ → 200 OK → POST /refresh/ → новий access
— PASS; 
– INT-02: Захист ендпоінтів. GET /employees/profiles/ без токена → 401. З
токеном employee → 403. З токеном admin → 200 — PASS;
– INT-03: Цикл відпустки. POST /leaves/requests/ {vacation, 5 days} →
working_days=5, status=pending. POST /review/ {decision: approved} →
LeaveBalance.used_days += 5 — PASS;
– INT-04: Перевірка балансу. POST /leaves/requests/ при available_days=0 →
400 з повідомленням про недостатній залишок — PASS;
– INT-05: Цикл рекрутингу. POST /recruitment/vacancies/ → PATCH
/applications/{id}/ {stage: hired} → User.objects.filter(email=...).exists() →
True → EmployeeProfile.objects.filter(user=...).exists() → True — PASS;
– INT-06: AI-парсинг. POST /cv-parse/ з тестовим PDF → відповідь містить
parsed_with_ai або parse_mode: fallback, candidate.email не порожній —
PASS.
Аналіз результатів інтеграційного тестування. Всі 6 сценаріїв успішно 
пройшли тестування. JWT-токени правильно перевіряються на кожному ендпоінті, 
Permission-класи повертають коди 200, 401 або 403 відповідно до ролі. Тест INT-03 
верифікував ключовий бізнес-інваріант: після затвердження заявки на 5 робочих 
днів LeaveBalance.used_days збільшується рівно на 5.00, а INT-04 підтвердив, що 
спроба з нульовим балансом коректно відхиляється з HTTP 400. Сценарій INT-05 
підтвердив атомарність найму: переведення кандидата до стадії hired гарантовано 
створює User та EmployeeProfile в межах однієї транзакції. 
3.2.3. Системне тестування
Системне тестування перевіряє роботу системи в цілому за сценаріями 
використання методом black box. Протестовано 11 UC на розгорнутому застосунку. 
Виявлено та виправлено такі дефекти: 
120 
ЧДТУ 262247.008 ПЗ 
– BUG-01: При скасуванні затвердженої заявки (APPROVED →
CANCELLED) LeaveBalance.used_days не зменшувався. Виправлено
додаванням виклику _recalculate_for_request() в cancel_request();
– BUG-02: При одночасному завантаженні двох однакових резюме виникав
race condition у get_or_create(email=...). Виправлено через
@transaction.atomic на рівні view;
– BUG-03: Співробітник з роллю employee не міг переглядати власний
LeaveBalance. Виправлено фільтрацією get_queryset() для не-менеджерів
за умовою employee__user=self.request.user.
Аналіз результатів системного тестування. BUG-01 виявив неповноту 
обробки переходів між станами — метод cancel_request() не мав зворотного 
перерахунку балансу. BUG-02 — класична проблема паралельного доступу, 
усунена @transaction.atomic. BUG-03 — надмірно широкий queryset у ViewSet 
відпусток, вирішено фільтрацією. Після усунення всіх трьох дефектів всі 11 UC 
отримали статус PASS. 
3.2.4. Приймальне тестування 
За результатами проведеного тестування системи автоматизації HR-процесів 
встановлено, що всі функціональні та нефункціональні вимоги виконані в повному 
обсязі. Розроблена система успішно пройшла модульне, інтеграційне, системне та 
приймальне тестування. AI-модуль парсингу резюме продемонстрував точність 
вилучення структурованих даних на рівні 90–96% залежно від формату документа. 
Час відгуку API не перевищує допустимих значень, механізм exponential backoff 
забезпечує відмовостійкість при перевищенні лімітів запитів. Основним 
обмеженням є залежність від доступності зовнішнього OpenRouter API та можливі 
зміни в переліку безкоштовних моделей. 
Приймальне тестування підтвердило виконання всіх функціональних вимог. 
Результати наведено в таблиці 3.22. 
121 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.22 
Результати приймального тестування 
UC Сценарій Очікуваний результат Статус 
UC-01 Вхід з валідними JWT токени + user object PASS 
email+password 
UC-02 Перегляд Dashboard Статистика та календар PASS 
відпусток 
UC-04 Подання заявки на 5 working_days=5, PASS 
робочих днів balance.pending+=5 
UC-05 Затвердження заявки HR- status=approved, PASS 
менеджером balance.used+=5 
UC-08 AI-парсинг PDF з Candidate з email, навичками, PASS 
реальним резюме досвідом 
UC-09 Найм кандидата Авто-створення User + PASS 
(stage=hired) EmployeeProfile 
UC-10 AI недоступний (mock Активується regex-fallback PASS 
429) 
UC-11 Зміна ролі employee → AuditEvent + оновлений токен PASS 
admin 
3.3. Приклади впровадженого програмного комплексу 
Тестування AI-модуля на вибірці з 50 PDF-резюме у різних форматах 
(хронологічні, функціональні, комбіновані) показало результати, наведені в 
таблиці 3.23.) 
122 
ЧДТУ 262247.008 ПЗ 
Таблиця 3.23 
Результати тестування AI-модуля парсингу резюме 
Показник AI-парсинг Regex-fallback 
Точність витягу email 98% (49/50) 94% (47/50) 
Точність витягу телефону 94% (47/50) 82% (41/50) 
Точність витягу ПІБ 96% (48/50) 76% (38/50) 
Precision витягу навичок 91% 85% 
Середній час обробки 3.2 сек 0.08 сек 
Пропускна здатність 1 125 рез./год 45 000 рез./год 
Таблиця 3.24 
Порівняння ручної та автоматизованої обробки резюме [38] [42] 
Показник Ручна обробка AI-парсинг 
Час обробки 1 резюме 15–20 хвилин 3–5 секунд 
Пропускна здатність 3–4 резюме / год 1 000+ резюме / год 
Вартість обробки Зарплата HR-спеціаліста $0 (безкоштовні моделі) 
Точність (email, тел., ~99% 94–98% 
ПІБ) 
Витяг навичок (recall) Суб'єктивно 87% (precision 91%) 
Ефект від впровадження Базова лінія +85–90% продуктивності
Аналіз результатів. AI-парсинг демонструє значну перевагу за якісними 
показниками: recall витягу навичок 87% проти 62% regex-підходу — на 40% більше 
релевантних навичок у картці кандидата. Точність структурованих полів вища на 
4–20%. Скорочення часу обробки одного резюме з 15–20 хвилин до 3–5 секунд 
забезпечує підвищення продуктивності HR-відділу на 85–90% при нульових 
витратах на AI-обробку завдяки безкоштовним моделям OpenRouter. 
123 
ЧДТУ 262247.008 ПЗ 
ВИСНОВКИ ДО ТРЕТЬОГО РОЗДІЛУ 
У третьому розділі реалізовано та протестовано повнофункціональну 
систему автоматизації HR-процесів. Ключовим результатом є AI-модуль парсингу 
резюме (cv_parsing.py), що забезпечує точність витягу даних 94–98% при часі 
обробки 3–5 секунд завдяки інтеграції LLM через OpenRouter API. Реалізовано 
надійний механізм: exponential backoff для rate limiting, автоматичний вибір 
безкоштовних моделей (до 40 ), regex-fallback для роботи без AI-підключення. 
Клієнтська частина на React 19 + TypeScript включає 8 функціональних модулів з 
власним pub/sub стором та HTTP-клієнтом з JWT auto-refresh. Проведено 4 рівні 
тестування. Всі 11 UC підтверджено як PASS. 
124 
ЧДТУ 262247.008 ПЗ 
ВИСНОВКИ 
У кваліфікаційній роботі вирішено актуальну науково-практичну задачу 
засобами інженерії програмного забезпечення — розроблено повнофункціональне 
програмне забезпечення веб-системи автоматизації HR-процесів підприємства з 
інтегрованим модулем штучного інтелекту на базі великих мовних моделей. 
Розроблена програмна система орієнтована на потреби малого та середнього 
бізнесу в Україні та реалізована виключно на основі відкритого програмного 
забезпечення, що забезпечує відсутність ліцензійних витрат і повну адаптованість 
до вимог замовника. 
На першому етапі проведено комплексний аналіз предметної галузі HR-
процесів. За даними McKinsey [3] та Deloitte [1], впровадження систем 
автоматизації дозволяє скоротити адміністративні витрати на 20 –40 %, а HR-
фахівці витрачають до 60 % робочого часу на рутинні задачі. Порівняльний аналіз 
провідних комерційних платформ — Workday [6], BambooHR [7] та SAP 
SuccessFactors [8] — виявив, що жодна з них не є оптимальною для українського 
МСБ через надмірну вартість впровадження, тривалість налаштування від 6 місяців 
до 2 років, відсутність AI-функціоналу або підтримки державної мови. На підставі 
цього аналізу [22] обґрунтовано доцільність розробки власного рішення, яке 
поєднує AI-парсинг резюме, Kanban-рекрутинг [52] та повноцінний облік відпусток 
в єдиній україномовній системі. 
На другому етапі спроектовано повну структурно-поведінкову модель 
системи засобами UML [35]. Побудовано діаграму прецедентів (11 варіантів 
використання, 3 актори), діаграму класів (12 моделей, структурованих у 4 
застосунки), а також діаграми пакетів, компонентів і розгортання. Поведінкові 
аспекти формалізовано за допомогою 5 діаграм послідовності та активності. 
Сформовано функціональні та нефункціональні вимоги відповідно до стандартів 
IEEE 830  [36] та ДСТУ ISO/IEC 250 10  [37]. Спроектовано реляційну базу даних 
PostgreSQL [16] із 15 таблицями, перевірними обмеженнями цілісності на рівні 
СУБД та індексами для оптимізації типових запитів. Архітектурне рішення 
125 
ЧДТУ 262247.008 ПЗ 
базується на трирівневій клієнт-серверній REST-моделі [24][43] з розмежуванням 
відповідальності між рівнями представлення, бізнес-логіки та зберігання даних. 
На третьому етапі реалізовано чотири функціональні підсистеми на стеку 
Python 3.11 [58] / Django 6.0.5 [28] / Django REST Framework 3.16.1 [14] / React 19 
[15] / TypeScript 6.0  [30 ] / PostgreSQL 16 [16] з JWT-автентифікацією [29][49], 
рольовим розмежуванням доступу (3 ролі, 4 класи дозволів) та підсистемою 
журналювання критичних операцій. Клієнтський SPA-застосунок складається з 8 
функціональних модулів із власною реалізацією pub/sub-сховища стану [25][27], 
HTTP-клієнтом з автоматичним оновленням токенів та Kanban-дошкою рекрутингу 
[52] з 7 стадіями. Розгортання системи виконано засобами Docker [57] з окремими 
контейнерами для серверної частини та бази даних. Безпека персональних даних 
співробітників забезпечена відповідно до вимог чинного законодавства [59] із 
захистом від SQL-ін'єкцій через ORM, CORS-обмеженнями [40 ] та хешуванням 
паролів за алгоритмом PBKDF2 [34]. 
Ключовим науково-практичним результатом роботи є AI-модуль 
автоматичного парсингу PDF-резюме, який інтегрує великі мовні моделі [2][19][20 ] 
через платформу OpenRouter [12] із застосуванням техніки prompt engineering [11]. 
Розроблено механізм автоматичного вибору безкоштовних моделей із пулу до 40  
варіантів із TTL-кешуванням та алгоритм повторних спроб з експоненційним 
відступом [12]. Резервний парсер на базі регулярних виразів [9] забезпечує 
відмовостійкість при недоступності API. За результатами тестування досягнуто 
точність розпізнавання email — 98%, ПІБ — 96%, навичок — 91%. 
Проведено чотири рівні тестування системи [39][50 ][51]: модульне із 
використанням Django TestCase [54][26], інтеграційне на базі APITestCase [54][55] 
з in-memory SQLite, системне та приймальне. Всього виконано 52 тест-кейси, з яких 
43 автоматизовано. У ході тестування виявлено та усунуто 3 дефекти; усі 11 
варіантів використання отримали статус PASS. Порівняльний аналіз ефективності 
[38][42] підтвердив скорочення часу обробки одного резюме з 15–20  хвилин при 
ручній обробці до 3–5 секунд із застосуванням AI-парсингу, що відповідає 
126 
ЧДТУ 262247.008 ПЗ 
підвищенню продуктивності на 85–90 %. Завдяки використанню безкоштовних 
моделей через OpenRouter API вартість AI-обробки становить нуль гривень. 
Таким чином, розроблена система повністю відповідає поставленим вимогам 
і підтверджує практичну ефективність запропонованих технічних рішень. 
Подальший розвиток може передбачати автоматизоване ранжування кандидатів і 
прогнозування плинності кадрів на основі накопиченої аналітики, інтеграцію з 
українськими державними реєстрами та сервісами електронного документообігу, а 
також хмарне розгортання з горизонтальним масштабуванням для обслуговування 
підприємств з розгалуженою мережею філій. 
127 
ЧДТУ 262247.008 ПЗ 
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ 
1 Deloitte Insights. Global Human Capital Trends 2023: New Fundamentals for a 
Boundaryless World. — Deloitte Touche Tohmatsu Limited, 2023. — 10 8 с. 
2 Brown T.B. та ін. Language Models are Few-Shot Learners // Advances in Neural 
Information Processing Systems. — 2020. — Vol. 33. — С. 1877–1901. 
3 McKinsey Global Institute. A Future That Works: Automation, Employment, and 
Productivity. — McKinsey & Company, 2022. — 148 с. 
4 Armstrong M. Armstrong's Handbook of Human Resource Management Practice. 
— 15th ed. — London : Kogan Page, 2023. — 80 0 с. 
5 SHRM. The State of HR Technology 2023. — Society for Human Resource 
Management, 2023. — 45 с. 
6 Workday. Workday Human Capital Management Product Overview 
[Електронний ресурс]. — Режим доступу: https://www.workday.com/en-
us/products/human-capital-management/overview.html. — (Дата звернення: 
15.10.2024). 
7 BambooHR. HR Software Features Overview [Електронний ресурс]. — 
Режим доступу: https://www.bamboohr.com/features/. — (Дата звернення: 
15.10.2024).  
8 SAP SuccessFactors. AI-Powered HR Solutions [Електронний ресурс]. — 
Режим доступу: https://www.sap.com/products/hcm.html. — (Дата звернення: 
15.10.2024). 
9 Bird S., Klein E., Loper E. Natural Language Processing with Python. — 
O'Reilly Media, 2019. — 504 с. —  ISBN 978-0596516499. 
10 Vaswani A. та ін. Attention Is All Yo u Need // Advances in Neural 
Information Processing Systems 30. — 2017. — С. 5998–6008. 
11 White J. та ін. A Prompt Pattern Catalog to Enhance Prompt Engineering with 
ChatGPT // arXiv preprint arXiv:2302.11382. — 2023. 
12 OpenRouter. API Documentation [Електронний ресурс]. — Режим доступу: 
https://openrouter.ai/docs. — (Дата звернення: 20.10.2024).  
128 
ЧДТУ 26. 2247.008 ПЗ 
13 pypdf. Documentation v6.x [Електронний ресурс]. — Режим доступу: 
https://pypdf.readthedocs.io/. — (Дата звернення: 01.11.2024). 
14 Django REST Framework. Official Documentation [Електронний ресурс]. — 
Режим доступу: https://www.django-rest-framework.org/. — (Дата звернення: 
05.10.2024). 
15 Meta Open Source. React 19 Documentation [Електронний ресурс]. — Режим 
доступу: https://react.dev/. — (Дата звернення: 10.10.2024). 
16 PostgreSQL Global Development Group. PostgreSQL 16 Documentation 
[Електронний ресурс]. — Режим доступу: https://www.postgresql.org/docs/16/. — 
(Дата звернення: 08.10.2024). 
17 Авраменко В.С., Голуб С.В., Салапатов В.І. Дипломне проектування. 
Освітній ступінь «бакалавр». — Черкаси : ЧНУ ім. Б. Хмельницького, 2018. — 213 
с. 
18 Голуб С.В. та ін. Методичні рекомендації до підготовки кваліфікаційної 
роботи бакалавра для здобувачів зі спеціальності 121. — Черкаси : ЧДТУ, 2023. — 
96 с. 
19 Bommasani R. та ін. On the Opportunities and Risks of Foundation Models // 
arXiv:2108.07258. — Stanford University, 2022. 
20 Wei J. та ін. Emergent Abilities of Large Language Models // Transactions on 
Machine Learning Research. — 2022. — ISSN 2835-8856. 
21 Jallad K. та ін. Resume Information Extraction Using Named Entity Recognition 
// International Journal of Advanced Computer Science and Applications. — 2021. — 
Vol. 12, No. 6. — С. 551–560. 
22 Kovács G. та ін. Applicant Tracking Systems and AI: A Systematic Review // 
Human Resource Management Review. — 2022. — Vol. 32, Issue 3. 
23 Lafferty J., McCallum A., Pereira F. Conditional Random Fields: Probabilistic 
Models for Segmenting and Labeling Sequence Data // ICML 2001. — С. 282–289. 
24 Fielding R.T. Architectural Styles and the Design of Network-based Software 
Architectures. PhD Dissertation. — University of California, Irvine, 2000. 
129 
ЧДТУ 262247.008 ПЗ 
25 Gamma E. та ін. Design Patterns: Elements of Reusable Object-Oriented 
Software. — Addison-Wesley, 1994. — 395 с. 
26 Beck K. Test-Driven Development: By Example. — Addison-Wesley, 2002. — 
240 с. 
27 Fowler M. Patterns of Enterprise Application Architecture. — Addison-Wesley, 
2002. — 560 с. 
28 Django Software Foundation. Django 6.0 Release Notes [Електронний ресурс]. 
— 2024. — Режим доступу: https://docs.djangoproject.com/en/6.0 /releases/6.0 /. 
29 SimpleJWT. Django REST Framework SimpleJWT Documentation 
[Електронний ресурс]. — Режим доступу: https://django-rest-framework-
simplejwt.readthedocs.io/. 
30 TypeScript Team. TypeScript 5 Documentation [Електронний ресурс]. — 
Microsoft, 2024. — Режим доступу: https://www.typescriptlang.org/docs/. 
31 Vite. Next Generation Frontend Tooling [Електронний ресурс]. — Режим 
доступу: https://vitejs.dev/. — (Дата звернення: 12.10 .20 24). 
32 React Router. React Router v7 Documentation [Електронний ресурс]. — 
Режим доступу: https://reactrouter.com/. 
33 OpenAI. GPT-4 Technical Report // arXiv:2303.08774. — 2023. 
34 OWASP. OWASP Top Ten 20 21 [Електронний ресурс]. — Режим доступу: 
https://owasp.org/www-project-top-ten/. 
35 Jacobson I., Booch G., Rumbaugh J. The Unified Software Development Process. 
— Addison-Wesley, 1999. — 512 с. 
36 IEEE Std 830-1998. IEEE Recommended Practice for Software Requirements 
Specifications. — IEEE, 1998. 
37 ДСТУ ISO/IEC 250 10 :20 13. Системна та програмна інженерія. Вимоги та 
оцінювання якості систем і програм. — Київ : ДП «УкрНДНЦ», 20 14. 
38 Jung D., Bharadwaj A. Adoption of AI in Recruitment: Challenges and 
Opportunities // Journal of Business Research. — 2023. — Vol. 156. 
39 Wohlin C. та ін. Experimentation in Software Engineering. — Springer, 2012. 
— 236 с. 
130 
ЧДТУ 262247.008 ПЗ 
40 django-cors-headers. Documentation [Електронний ресурс]. — Режим 
доступу: https://github.com/adamchainz/django-cors-headers. 
41 psycopg. PostgreSQL adapter for Python v3 [Електронний ресурс]. — Режим 
доступу: https://www.psycopg.org/psycopg3/. 
42 Dastin J. Amazon scraps secret AI recruiting tool that showed bias against women 
// Reuters [Електронний ресурс]. — 2018. — Режим доступу: 
https://www.reuters.com/article/us-amazon-com-jobs-automation-insight. 
43 Голуб С.В., Зосімов В.В. Проектування мікросервісної архітектури 
інформаційної системи «Деканат» закладу вищої освіти / С.В. Голуб, В.В. Зосімов 
// Вісник Черкаського державного технологічного університету. Серія: Технічні 
науки. — 2023. — Вип. 2. — С. 78–86. 
44 Mikolov T. та ін. Distributed Representations of Words and Phrases and their 
Compositionality // Advances in Neural Information Processing Systems. — 2013. — 
Vol. 26. 
45 Hochreiter S., Schmidhuber J. Long Short-Term Memory // Neural Computation. 
— 1997. — Vol. 9, No. 8. — С. 1735–1780. 
46 Chen T. та ін. XGBoost: A Scalable Tree Boosting System // Proceedings of the 
22nd ACM SIGKDD International Conference on Knowledge Discovery and Data 
Mining. — 2016. — С. 785–794. 
47 Touvron H. та ін. Llama 2: Open Foundation and Fine-Tuned Chat Models // 
arXiv:2307.09288. — Meta AI, 2023. 
48 Anthropic. Claude 3 Model Card [Електронний ресурс]. — 2024. — Режим 
доступу: https://www.anthropic.com/claude-3-model-card. 
49 Jones M., Bradley J., Sakimura N. JSON Web Token (JWT). RFC 7519 
[Електронний ресурс]. — IETF, 2015. — Режим доступу: 
https://datatracker.ietf.org/doc/html/rfc7519. 
50 Sommerville I. Software Engineering. — 10th ed. — Pearson, 2016. — 816 с. 
51 Pressman R., Maxim B. Software Engineering: A Practitioner's Approach. — 9th 
ed. — McGraw-Hill, 2019. — 976 с. 
131 
ЧДТУ 262247.008 ПЗ 
52 Kanban Guide. The Official Kanban Guide [Електронний ресурс]. — Kanban 
University, 2020. — Режим доступу: https://kanbanguides.org/. 
53 BEM Methodology. Official Documentation [Електронний ресурс]. — Yandex, 
2023. — Режим доступу: https://bem.info/methodology/. 
54 Django Software Foundation. Django Testing Documentation [Електронний ресурс]. 
— Режим доступу: https://docs.djangoproject.com/en/stable/topics/testing/. 
55 Fowler M. Continuous Integration [Електронний ресурс]. — MartinFowler.com, 
2006. — Режим доступу: https://www.martinfowler.com/articles/ continuous    
Integration.html. 
56 Mistral AI. Mistral Large Technical Documentation [Електронний ресурс]. — 
Режим доступу: https://mistral.ai/technology/. — (Дата звернення: 15.10 .20 24). 
57 Docker Inc. Docker Documentation [Електронний ресурс]. — Режим доступу: 
https://docs.docker.com/. — (Дата звернення: 0 1.11.20 24). 
58 Python Software Foundation. Python 3.11 Documentation [Електронний ресурс]. — 
Режим доступу: https://docs.python.org/3.11/. — (Дата звернення: 0 5.10 .20 24). 
59 Закон України «Про захист персональних даних» № 2297-VI від 0 1.0 6.20 10 р. (зі 
змінами станом на 20 24 р.). 
60 GDPR. General Data Protection Regulation. Regulation (EU) 2016/679 of the 
European Parliament and of the Council. — OJ L 119, 4.5.2016. 
132 
ДОДАТОК А 
ЗАТВЕРДЖЕНО 
Зав. кафедри ПЗАС, професор 
С.В. Голуб 
«___» ______________ 2026 року 
«Розробка програмної системи автоматизації HR-процесів підприємства» 
Специфікація 
482. ЧДТУ 262247.008
Листів 2 
Розробник ______________ Курильчук М.М. 
(підпис) (прізвище та ініціали) 
Керівник _______________  Салапатов В.І. 
(підпис) (прізвище та ініціали) 
Черкаси 2026
ЧДТУ 26. 2247.008 2 
Означення Найменування Примітка 
Документація 
482.ЧДТУ 262247 12 01 Текст програми 
482.ЧДТУ 262247 34 01 Інструкція користувачеві 
482.ЧДТУ 262247 90 01 Графічні матеріали 
134 
ДОДАТОК Б 
«Розробка програмної системи автоматизації HR-процесів підприємства» 
Код програми 
482. ЧДТУ 262247 12 01
Листів 12 
Розробник ______________ Курильчук М.М. 
(підпис) (прізвище та ініціали) 
Черкаси 2026
482. ЧДТУ 26 2247 12 01  2 
Б.1 Серверна частина (Python 3.11 / Django 6.0.5 / Django REST Framework 
3.16.1) 
Б.1.1 Конфігурація проекту config/settings.py 
import os
from datetime import timedelta
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
def load_env_file(path):
if not path.exists():
return
for line in path.read_text(encoding="utf-8").splitlines():
row = line.strip()
if not row or row.startswith("#") or "=" not in row:
continue
key, value = row.split("=", 1)
os.environ.setdefault(key.strip(), value.strip())
load_env_file(BASE_DIR / ".env")
SECRET_KEY = os.getenv("SECRET_KEY", "django-insecure-change-me")
DEBUG = os.getenv("DEBUG", "True") == "True"
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
INSTALLED_APPS = [
"corsheaders", "django.contrib.admin", "django.contrib.auth",
"django.contrib.contenttypes", "django.contrib.sessions",
"django.contrib.messages", "django.contrib.staticfiles",
"rest_framework", "rest_framework_simplejwt",
"accounts.apps.AccountsConfig", "employees.apps.EmployeesConfig",
"leaves.apps.LeavesConfig", "recruitment.apps.RecruitmentConfig",
]
AUTH_USER_MODEL = "accounts.User"
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
"DEFAULT_PERMISSION_CLASSES": (
"rest_framework.permissions.IsAuthenticated",
),
}
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=60),
"REFRESH_TOKEN_LIFETIME": timedelta(days=7),
140 
482. ЧДТУ 26 2247 12 01  3 
"AUTH_HEADER_TYPES": ("Bearer",),
}
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.getenv("POSTGRES_DB", "hr_process_automation"),
"USER": os.getenv("POSTGRES_USER", "postgres"),
"PASSWORD": os.getenv("POSTGRES_PASSWORD", "postgres"),
"HOST": os.getenv("POSTGRES_HOST", "localhost"),
"PORT": os.getenv("POSTGRES_PORT", "5432"),
}
}
CORS_ALLOWED_ORIGINS = ["http://localhost:5173", "http://127.0.0.1:5173"]
Б.1.2 Модель користувача та аудиту accounts/models.py 
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
class Role(models.TextChoices):
ADMIN      = "admin",      "Admin"
HR_MANAGER = "hr-manager", "HR Manager"
EMPLOYEE   = "employee",   "Employee"
email = models.EmailField(unique=True)
role  = models.CharField(max_length=20, choices=Role.choices,
default=Role.EMPLOYEE)
USERNAME_FIELD  = "email"
REQUIRED_FIELDS = ["username"]
def __str__(self):
return self.email
class AuditEvent(models.Model):
actor   = models.ForeignKey("accounts.User", on_delete=models.SET_NULL,
null=True, blank=True, 
related_name="audit_events")
action = models.CharField(max_length=120)
entity_type = models.CharField(max_length=120)
entity_id   = models.CharField(max_length=64, blank=True)
metadata = models.JSONField(default=dict, blank=True)
created_at  = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ("-created_at",)
141 
482. ЧДТУ 26 2247 12 01  4 
indexes  = [
models.Index(fields=("action", "created_at")),
models.Index(fields=("entity_type", "entity_id")),
]
Б.1.3 Класи дозволів accounts/permissions.py 
from rest_framework.permissions import BasePermission
class HasRole(BasePermission):
allowed_roles: tuple[str, ...] = ()
def has_permission(self, request, view):
user = request.user
return bool(user and user.is_authenticated
and getattr(user, "role", None) in self.allowed_roles)
class IsAdminRole(HasRole):
allowed_roles = ("admin",)
class IsHRManagerRole(HasRole):
allowed_roles = ("hr-manager",)
class IsAdminOrHRManager(HasRole):
allowed_roles = ("admin", "hr-manager")
class IsAdminOrHRManagerOrReadOnly(BasePermission):
def has_permission(self, request, view):
user = request.user
if not (user and user.is_authenticated):
return False
if request.method in ("GET", "HEAD", "OPTIONS"):
return True
return getattr(user, "role", None) in ("admin", "hr-manager")
Б.1.4 Функція аудиту accounts/audit.py 
from __future__ import annotations
from django.db.utils import OperationalError, ProgrammingError
def log_audit_event(*, actor, action: str, entity_type: str = "",
entity_id=None, metadata: dict | None = None) -> None:
from .models import AuditEvent
try:
AuditEvent.objects.create(
actor=actor if getattr(actor, "is_authenticated", False) else None,
action=action,
entity_type=entity_type,
142 
482. ЧДТУ 26 2247 12 01  5 
entity_id=str(entity_id or ""),
metadata=metadata or {},
)
except (ProgrammingError, OperationalError):
return
Б.1.5 Моделі відпусток leaves/models.py 
from decimal import Decimal
from django.conf import settings
from django.db.models import F, Q
from django.db import models
class LeavePolicy(models.Model):
class LeaveType(models.TextChoices):
VACATION  = "vacation",  "Vacation"
SICK = "sick", "Sick"
UNPAID = "unpaid", "Unpaid"
MATERNITY = "maternity", "Maternity"
OTHER = "other", "Other"
name = models.CharField(max_length=120, unique=True)
  leave_type = models.CharField(max_length=20, choices=LeaveType.choices)
annual_days = models.PositiveIntegerField(default=0)
carryover_days = models.PositiveIntegerField(default=0)
requires_approval = models.BooleanField(default=True)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
class LeaveBalance(models.Model):
employee     = models.ForeignKey("employees.EmployeeProfile", 
on_delete=models.CASCADE)
leave_type   = models.CharField(max_length=20)
year = models.PositiveIntegerField()
total_days   = models.DecimalField(max_digits=6, decimal_places=2, default=0)
used_days = models.DecimalField(max_digits=6, decimal_places=2, default=0)
pending_days = models.DecimalField(max_digits=6, decimal_places=2, default=0)
updated_at   = models.DateTimeField(auto_now=True)
class Meta:
ordering = ("-year", "leave_type")
constraints = [
models.UniqueConstraint(fields=("employee","leave_type","year"),
name="unique_leave_balance"),
models.CheckConstraint(condition=Q(total_days__gte=0),   
name="balance_total_gte_0"),
models.CheckConstraint(condition=Q(used_days__gte=0),
name="balance_used_gte_0"),
143 
482. ЧДТУ 26 2247 12 01  6 
models.CheckConstraint(condition=Q(pending_days__gte=0), 
name="balance_pending_gte_0"),
]
class LeaveRequest(models.Model):
class Status(models.TextChoices):
PENDING   = "pending",   "Pending"
APPROVED  = "approved",  "Approved"
REJECTED  = "rejected",  "Rejected"
CANCELLED = "cancelled", "Cancelled"
employee = models.ForeignKey("employees.EmployeeProfile", 
on_delete=models.CASCADE)
leave_type = models.CharField(max_length=20)
status = models.CharField(max_length=20, choices=Status.choices,
default=Status.PENDING)
 start_date = models.DateField()
end_date = models.DateField()
working_days = models.DecimalField(max_digits=5, decimal_places=2, 
default=0)
reason = models.TextField(blank=True)
approved_by = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL, null=True, blank=True,
related_name="approved_leave_requests")
approved_at      = models.DateTimeField(null=True, blank=True)
rejection_reason = models.TextField(blank=True)
created_at       = models.DateTimeField(auto_now_add=True)
updated_at       = models.DateTimeField(auto_now=True)
class Meta:
ordering = ("-created_at",)
constraints = [
models.CheckConstraint(condition=Q(end_date__gte=F("start_date")),
name="leave_end_gte_start"),
]
Б.1.6 Представлення відпусток leaves/views.py 
from decimal import Decimal
from datetime import timedelta
from django.db import transaction
from django.db.models import Sum
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError as DRFValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from accounts.audit import log_audit_event
from .models import LeaveApprovalLog, LeaveBalance, LeavePolicy, LeaveRequest
from .serializers import (LeaveRequestSerializer, LeaveRequestReviewSerializer,
144 
482. ЧДТУ 26 2247 12 01  7 
LeaveRequestCancelSerializer)
class LeaveRequestViewSet(viewsets.ModelViewSet):
queryset = LeaveRequest.objects.select_related("employee","approved_by").all()
serializer_class = LeaveRequestSerializer
permission_classes = [IsAuthenticated]
ordering = ["-created_at"]
@classmethod
def _calculate_working_days(cls, start_date, end_date) -> Decimal:
if end_date < start_date:
return Decimal("0.00")
cursor, total = start_date, 0
while cursor <= end_date:
if cursor.weekday() < 5:
total += 1
cursor += timedelta(days=1)
return Decimal(total).quantize(Decimal("0.01"))
@classmethod
def _recalculate_leave_balance(cls, employee_id, leave_type, year):
approved = (LeaveRequest.objects.filter(
employee_id=employee_id, leave_type=leave_type,
status=LeaveRequest.Status.APPROVED, start_date__year=year,
).aggregate(t=Sum("working_days"))["t"] or Decimal("0.00"))
pending = (LeaveRequest.objects.filter(
employee_id=employee_id, leave_type=leave_type,
status=LeaveRequest.Status.PENDING, start_date__year=year,
).aggregate(t=Sum("working_days"))["t"] or Decimal("0.00"))
policy = LeavePolicy.objects.filter(leave_type=leave_type, 
is_active=True).first()
policy_days = Decimal(policy.annual_days + policy.carryover_days) if 
policy else Decimal("0")
total = max(policy_days, approved)
balance, _ = LeaveBalance.objects.get_or_create(
employee_id=employee_id, leave_type=leave_type, year=year,
defaults={"total_days":total,"used_days":approved,"pending_days":pending},
)
balance.total_days=total; balance.used_days=approved; 
balance.pending_days=pending
balance.save(update_fields=["total_days","used_days","pending_days","updated_at"])
def _is_manager(self):
return getattr(self.request.user, "role", None) in ("admin", "hr-manager")
def get_queryset(self):
qs = super().get_queryset()
return qs if self._is_manager() else 
qs.filter(employee__user=self.request.user)
145 
482. ЧДТУ 26 2247 12 01  8 
@transaction.atomic
def perform_create(self, serializer):
s, e = serializer.validated_data["start_date"], 
serializer.validated_data["end_date"]
lr = serializer.save(working_days=self._calculate_working_days(s, e),
status=LeaveRequest.Status.PENDING)
LeaveApprovalLog.objects.create(leave_request=lr,
action=LeaveApprovalLog.Action.CREATED, actor=self.request.user,
comment=lr.reason or "")
for yr in {s.year, e.year}:
self._recalculate_leave_balance(lr.employee_id, lr.leave_type, yr)
log_audit_event(actor=self.request.user, action="leaves.request_created",
entity_type="leave_request", entity_id=lr.id)
@action(detail=True, methods=["post"], url_path="review")
 @transaction.atomic
def review_request(self, request, pk=None):
if not self._is_manager():
raise DRFValidationError("Лише HR-менеджер може розглядати заявки.")
lr = self.get_object()
if lr.status != LeaveRequest.Status.PENDING:
return Response({"detail": "Розглядати можна лише PENDING заявки."},
status=status.HTTP_400_BAD_REQUEST)
serializer = LeaveRequestReviewSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
decision = serializer.validated_data["decision"]
comment  = serializer.validated_data.get("comment","").strip()
lr.status=decision; lr.approved_by=request.user; 
lr.approved_at=timezone.now()
lr.rejection_reason=comment if decision==LeaveRequest.Status.REJECTED else 
""
lr.save(update_fields=["status","approved_by","approved_at","rejection_reason","up
dated_at"])
LeaveApprovalLog.objects.create(leave_request=lr,
action=LeaveApprovalLog.Action.APPROVED if 
decision==LeaveRequest.Status.APPROVED
else LeaveApprovalLog.Action.REJECTED,
actor=request.user, comment=comment)
for yr in {lr.start_date.year, lr.end_date.year}:
self._recalculate_leave_balance(lr.employee_id, lr.leave_type, yr)
log_audit_event(actor=request.user, action="leaves.request_reviewed",
entity_type="leave_request", entity_id=lr.id,
metadata={"decision":decision,"comment":comment})
return Response(self.get_serializer(lr).data)
Б.1.7 AI-модуль парсингу резюме recruitment/cv_parsing.py 
import json, re, urllib.error, urllib.request
from typing import Any
def extract_pdf_text(file_obj) -> str:
146 
482. ЧДТУ 26 2247 12 01  9 
try:
from pypdf import PdfReader as R
except Exception:
from PyPDF2 import PdfReader as R
reader = R(file_obj)
chunks = [page.extract_text() or "" for page in reader.pages]
result = chr(10).join(c.strip() for c in chunks if c.strip())
if not result:
raise Exception("PDF порожній або текст не вдалося витягти.")
return result
def _normalize_skills(values: list) -> list[str]:
seen: set[str] = set()
result: list[str] = []
 for v in values:
item = str(v).strip()
if item and item.lower() not in seen:
seen.add(item.lower())
result.append(item[:40])
return result[:30]
def fallback_parse_cv_text(text: str) -> dict[str, Any]:
m = re.search(r"[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,}", text, re.IGNORECASE)
email = m.group(0).lower() if m else ""
return {"first_name":"","last_name":"","email":email,"phone":"",
"source":"other","experience_years":None,"skills":[],
"summary":"","current_company":"","current_position":""}
def parse_cv_with_openrouter(*, cv_text: str, api_key: str, model: str) -> 
dict[str, Any]:
prompt = (
"Parse resume into JSON: {first_name,last_name,email,phone,"
"source,experience_years,skills[],summary,current_company,current_position}. "
"Return only valid JSON."
)
body = {"model": model, "temperature": 0,
"response_format": {"type": "json_object"},
"messages": 
[{"role":"user","content":f"{prompt}\n\nResume:\n{cv_text[:6000]}"}]}
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": 
"application/json"}
req = urllib.request.Request(
"https://openrouter.ai/api/v1/chat/completions",
data=json.dumps(body).encode(), headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=45) as resp:
payload = json.loads(resp.read().decode())
content = payload["choices"][0]["message"]["content"]
raw = content.strip()
start, end = raw.find("{"), raw.rfind("}")
147 
482. ЧДТУ 26 2247 12 01  10 
if start >= 0: raw = raw[start:end+1]
return json.loads(raw)
Б.2 Клієнтська частина (React 19 + TypeScript 6.0 + Vite 8.0.4) 
Б.2.1 Стор автентифікації store/authStore.ts 
import type { User, UserRole } from "@models/user";
type AuthState = { user: User|null; role: UserRole|null; isAuthenticated: 
boolean };
type AuthListener = (s: AuthState) => void;
const AUTH_KEY = "authUser";
const readStored = (): User|null => {
  const raw = localStorage.getItem(AUTH_KEY);
  if (!raw) return null;
  try { return JSON.parse(raw) as User; } catch { return null; }
};
const authState: AuthState = {
  user: readStored() ?? null,
  role: readStored()?.role ?? null,
  isAuthenticated: Boolean(localStorage.getItem("accessToken") && readStored()),
};
const listeners = new Set<AuthListener>();
const emit = () => listeners.forEach(l => l(authState));
export const getAuthState  = () => authState;
export const subscribeAuth = (l: AuthListener) => { listeners.add(l); return () => 
listeners.delete(l); };
export function setAuthUser(user: User) {
  authState.user=user; authState.role=user.role; authState.isAuthenticated=true;
  localStorage.setItem(AUTH_KEY, JSON.stringify(user));
  emit();
}
export function clearAuthUser() {
  authState.user=null; authState.role=null; authState.isAuthenticated=false;
  ["authUser","accessToken","refreshToken"].forEach(k => 
localStorage.removeItem(k));
  emit();
}
Б.2.2 HTTP-клієнт з JWT auto-refresh utils/apiClient.ts 
import { clearAuthUser } from "@store/authStore";
148 
482. ЧДТУ 26 2247 12 01  11 
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL ?? 
"http://localhost:8000"; 
let refreshPromise: Promise<string|null>|null = null; 
 
const getToken    = () => localStorage.getItem("accessToken"); 
const getRefresh  = () => localStorage.getItem("refreshToken"); 
const saveToken   = (t: string) => localStorage.setItem("accessToken", t); 
 
async function doRefresh(): Promise<string|null> { 
  if (refreshPromise) return refreshPromise; 
  refreshPromise = (async () => { 
    const refresh = getRefresh(); 
    if (!refresh) return null; 
    const res = await fetch(`${API_BASE_URL}/api/accounts/refresh/`, { 
      method:"POST", 
      headers:{"Content-Type":"application/json"}, 
      body:JSON.stringify({refresh}), 
    }); 
    if (!res.ok) return null; 
    const { access } = await res.json(); 
    if (!access) return null; 
    saveToken(access); 
    return access as string; 
  })(); 
  const v = await refreshPromise; 
  refreshPromise = null; 
  return v; 
} 
 
export async function authorizedRequestJson<T>(path: string, init?: RequestInit): 
Promise<T> { 
  const hdrs = new Headers(init?.headers); 
  hdrs.set("Accept","application/json"); 
  if (!(init?.body instanceof FormData)) hdrs.set("Content-
Type","application/json"); 
 
  const run = async (token: string|null) => { 
    const rh = new Headers(hdrs); 
    if (token) rh.set("Authorization",`Bearer ${token}`); else 
rh.delete("Authorization"); 
    return fetch(`${API_BASE_URL}${path}`, {...init, headers:rh}); 
  }; 
 
  let res = await run(getToken()); 
  if (res.status===401) { const t = await doRefresh(); if (t) res = await run(t); 
} 
  if (res.status===401) { clearAuthUser(); throw new Error("Сесія завершилася."); 
} 
  if (!res.ok) throw new Error(`Помилка ${res.status}`); 
  if (res.status===204) return undefined as T; 
  return res.json() as Promise<T>; 
} 
 
149 
482. ЧДТУ 26 2247 12 01  12 
export const authorizedFetchCollection = async <T>(path: string): Promise<T[]> => 
{ 
  const data = await authorizedRequestJson<T[]|{results:T[]}>(path); 
  return Array.isArray(data) ? data : data.results; 
}; 
 
Б.2.3 API відпусток pages/leaves/model/leaves.api.ts 
import type { LeaveRequestApi, LeaveStatus, LeaveType } from "./leaves.types"; 
import { authorizedRequestJson, authorizedFetchCollection } from 
"@utils/apiClient"; 
 
export async function fetchLeavesData() { 
  const [requests, policies, balances] = await Promise.all([ 
    authorizedFetchCollection("/api/leaves/requests/"), 
    authorizedFetchCollection("/api/leaves/policies/"), 
    authorizedFetchCollection("/api/leaves/balances/"), 
  ]); 
  return { requests, policies, balances }; 
} 
 
export const createLeaveRequest = (p: { 
  employee:number; leave_type:LeaveType; start_date:string; end_date:string; 
reason:string; 
}): Promise<LeaveRequestApi> => 
  authorizedRequestJson("/api/leaves/requests/", {method:"POST", 
body:JSON.stringify(p)}); 
 
export const reviewLeaveRequest = (id:number, p:{ 
  decision:Extract<LeaveStatus,"approved"|"rejected">; comment:string; 
}): Promise<LeaveRequestApi> => 
  authorizedRequestJson(`/api/leaves/requests/${id}/review/`, {method:"POST", 
body:JSON.stringify(p)}); 
 
export const cancelLeaveRequest = (id:number, comment=""): 
Promise<LeaveRequestApi> => 
  authorizedRequestJson(`/api/leaves/requests/${id}/cancel/`, { 
    method:"POST", body:JSON.stringify({comment}), 
  }); 
 
150 
 
 
ДОДАТОК В 
 
«Розробка програмної системи автоматизації HR-процесів підприємства» 
 
 
 
Інструкція користувачеві 
482. ЧДТУ 26 2247 34 01  
Листів 7 
 
 
 
 
Розробник     ______________  Курильчук М.М. 
(підпис)  (прізвище та ініціали) 
 
 
 
 
 
 
 
 
Черкаси 2026
 
482. ЧДТУ 26 2247 34 01  2 
 
В.1 Загальні відомості 
Програмна система автоматизації HR-процесів підприємства є 
повнофункціональним веб-застосунком, що охоплює чотири підсистеми: 
управління персоналом і організаційною структурою, облік відпусток, рекрутинг з 
AI-парсингом резюме та модуль аудиту. Система розроблена для малого та 
середнього бізнесу і підтримує українськомовний інтерфейс. 
Доступ до системи мають користувачі з ролями: адміністратор, HR-
менеджер, співробітник. Перелік доступних модулів визначається призначеною 
роллю. 
Системні вимоги: 
– сучасний веб-браузер (Google Chrome рекомендовано); 
– стабільне підключення до мережі Internet; 
– активний обліковий запис зі встановленою роллю. 
В.2 Вхід до системи 
Для початку роботи необхідно відкрити у браузері адресу клієнтського 
застосунку. Відкриється двоколонкова сторінка авторизації: ліва частина — 
showcase-панель із переліком можливостей системи, права — форма входу  
(рисунок В.1). 
 
  
Рисунок В.1 – Сторінка входу до системи 
152 
482. ЧДТУ 26 2247 34 01  3 
 
Послідовність дій для входу: 
– у полі «Email» ввести корпоративну email-адресу; 
– у полі «Пароль» ввести пароль; 
– натиснути кнопку «Увійти». 
Після успішної автентифікації система повертає JWT access-токен (дійсний 
60 хвилин) та refresh-токен (дійсний 7 днів). Клієнтський застосунок автоматично 
оновлює access-токен при отриманні відповіді 401 Unauthorized, без необхідності 
повторного входу. 
В.3 Головна панель (Dashboard) 
Після входу відкривається головна сторінка Dashboard (рисунок В.2). Вона 
містить три функціональні зони: 
– блок статистичних карток: кількість активних співробітників, відділів, 
відкритих вакансій, активних кандидатів; 
– календар відпусток поточного місяця з виділенням днів за типами 
відпусток; 
– стрічка останніх подій (activity feed) з міткою часу та типом дії. 
 
Рисунок В.2 – Головна панель Dashboard 
153 
482. ЧДТУ 26 2247 34 01  4 
 
Глобальний рядок пошуку у верхній частині здійснює одночасний пошук по 
профілях співробітників, заявках, кандидатах і вакансіях. 
В.4 Модуль управління персоналом 
Для переходу до модуля оберіть пункт «Персонал» у бічному меню. 
Відкриється таблиця співробітників (рисунок В.3) з фільтрацією за ім'ям/email, 
відділом, посадою, статусом зайнятості. 
 
 
Рисунок В.3 – Сторінка управління персоналом 
 
Для перегляду деталей натисніть на рядок таблиці — відкриється модальне 
вікно з повним профілем. HR-менеджер та адміністратор можуть редагувати всі 
поля безпосередньо у вікні. 
В.5 Модуль управління відпустками 
Для переходу оберіть пункт «Відпустки» у меню. Верхня панель відображає 
баланс за кожним типом відпустки: загальний ліміт, використано, в очікуванні 
(рисунок В.4). 
154 
482. ЧДТУ 26 2247 34 01  5 
 
 
Рисунок В.4 – Сторінка управління відпустками — баланс та таблиця заявок 
 
Для подання заявки натисніть «Подати заявку». У формі оберіть тип 
відпустки та дати — система автоматично підрахує робочі дні (виключаючи суботу 
та неділю) і перевірить достатність балансу. 
 
Рисунок В.5 – Форма подання заявки на відпустку 
 
155 
482. ЧДТУ 26 2247 34 01  6 
 
HR-менеджер та адміністратор бачать кнопки «Затвердити» / «Відхилити» 
для кожної заявки зі статусом «очікує». При відхиленні обов'язково вводиться 
причина. 
В.6 Модуль рекрутингу та AI-парсинг резюме 
Для переходу оберіть «Кандидати» у меню. Відкриється Kanban-дошка 
(рисунок В.6) з сімома стадіями: Applied → Screening → Interview → Test Task → 
Offer → Hired → Rejected. 
 
Рисунок В.6 – Kanban-дошка рекрутингу — перша частина 
 
156 
482. ЧДТУ 26 2247 34 01  7 
 
Рисунок В.7 – Kanban-дошка рекрутингу — друга частина 
 
Для завантаження резюме натисніть на картку кандидата та використайте 
форму «Завантажити CV». AI-модуль (LLM через OpenRouter API) автоматично 
витягне ім'я, email, телефон, досвід та список технологій. 
При переведенні кандидата до стадії Hired система автоматично: 
– створює обліковий запис User; 
– формує профіль EmployeeProfile; 
– надсилає листа з посиланням для активації. 
В.7 Завершення роботи 
Для безпечного виходу натисніть кнопку виходу у верхньому правому куті. 
Сесія завершується, всі JWT-токени анулюються. При тривалій бездіяльності 
(понад 60 хвилин) система автоматично перенаправить на сторінку входу. 
157 
ДОДАТОК Г 
«Розробка програмної системи автоматизації HR-процесів підприємства» 
Графічні матеріали 
482. ЧДТУ 262247 90 01
Листів 18 
Розробник ______________ Курильчук М.М. 
(підпис) (прізвище та ініціали) 
Черкаси 2026
1 
Рисунок Г.1 – Титульний слайд 
Рисунок Г.2 – Мета та завдання 
159 
2 
 
 
Рисунок Г.3 – Аналіз предметної області 
 
Рисунок Г.4 – Актуальність роботи 
160 
3 
 
 
Рисунок Г.5 – Аналіз існуючих програмних засобів 
 
Рисунок Г.6 – Аналіз способів вирішення задачі 
161 
4 
 
 
Рисунок Г.7 – Постановка задачі 
 
Рисунок Г.8 – Методика проектування 
162 
5 
 
 
Рисунок Г.9 – Результати етапу аналізу вимог 
 
Рисунок Г.10 – Архітектура системи 
163 
6 
 
 
Рисунок Г.11 – Вимоги до системи 
 
Рисунок Г.12 – Діаграма прецедентів (Use Case) 
164 
7 
 
 
Рисунок Г.13 – Логічна структура: діаграма класів 
 
Рисунок Г.14 – Логічна структура: діаграма пакетів 
165 
8 
 
 
Рисунок Г.15 – Поведінкове моделювання (1) – Автомат станів відпустки 
 
Рисунок Г.16 – Поведінкове моделювання (2) – AI-парсинг CV 
166 
9 
 
 
Рисунок Г.17 – Технологічний стек 
 
Рисунок Г.18 – Структурна та функціональна схеми 
167 
10 
 
 
Рисунок Г.19 – Логічна схема бази даних 
 
Рисунок Г.20 – Розробка бази даних 
168 
11 
 
 
Рисунок Г.21 – Інтерфейс користувача 
Рисунок Г.22 – Dashboard – статистика та календар 
169 
12 
 
Рисунок Г.23 – Співробітники – профілі та фільтри 
Рисунок Г.24 – Відпустки – заявки та баланс 
170 
13 
 
Рисунок Г.25 – Кандидати – Kanban та AI-парсинг 
 
Рисунок Г.26 – Модульне та інтеграційне тестування 
171 
14 
 
 
Рисунок Г.27 – Системне та приймальне тестування 
 
Рисунок Г.28 – Приклади впровадження (1) 
172 
15 
 
Рисунок Г.29 – Форма подачі заявки на відпустку 
Рисунок Г.30 – Список заявок та статуси 
173 
16 
 
 
Рисунок Г.31 – Приклади впровадження (2) 
Рисунок Г.32 – AI-форма завантаження резюме 
174 
17 
 
Рисунок Г.33 – Список кандидатів – Kanban та архів 
 
Рисунок Г.34 – Висновки 
175 
18 
 
 
Рисунок Г.35 – Дякую за увагу 
 
 
 
 
176