v0.5.3
Example document / build (push) Has been cancelled
Python application / build (push) Has been cancelled

- Мелкие исправления увеличивающие работу конвертера
This commit is contained in:
Igor20264
2026-09-10 10:50:15 +03:00
parent 510f7e7adf
commit e6b58efeb3
95 changed files with 7165 additions and 8771 deletions
+281
View File
@@ -0,0 +1,281 @@
# *СОДЕРЖАНИЕ
[TOC]
# *ВВЕДЕНИЕ
Обслуживание парка оборудования в производственных подразделениях опирается на заявки, которые до сих пор часто передаются по телефону и фиксируются в электронных таблицах. При таком порядке теряется история обращений, а срок реакции зависит от загруженности диспетчера.
Объектом работы является процесс приёма и исполнения заявок на техническое обслуживание. Предмет работы — архитектура и программная реализация модуля учёта таких заявок.
Цель работы — спроектировать и реализовать модуль учёта заявок, обеспечивающий регистрацию обращений, контроль сроков исполнения и хранение истории обслуживания.
Для достижения цели решаются следующие задачи:
1. Проанализировать процесс обработки заявок и существующие решения для его автоматизации.
2. Сформировать требования к модулю и спроектировать его архитектуру и модель данных.
3. Реализовать ключевые функции модуля и оценить объём хранилища.
В работе применяются структурный анализ процессов, объектно-ориентированное моделирование в нотации UML и сравнительный анализ программных решений.
# 1 Анализ процесса обработки заявок
## 1.1 Описание процесса и его участников
В обработке заявки участвуют три роли: инициатор со стороны производственного подразделения, диспетчер службы обслуживания и исполнитель. Инициатор сообщает о неисправности, диспетчер регистрирует обращение и назначает исполнителя, исполнитель выполняет работы и закрывает заявку.
Границы автоматизируемого процесса и его внешние интерфейсы приведены на @Рисунок:idef_a0.
%idef_a0 Контекстная диаграмма процесса обслуживания
```idef0
title Обработать заявку на обслуживание
node A-0
number 1
project Модуль учёта заявок
context TOP
[A0] Обработать заявку на обслуживание
<- Обращение инициатора
^ Регламент технического обслуживания
-> Закрытая заявка с отметкой о работах
v Служба обслуживания
```
Наблюдение за работой диспетчера в течение недели дало следующие показатели: в среднем 42 обращения в сутки, среднее время регистрации 6 минут, доля обращений с неполными сведениями об оборудовании 18 %. Именно неполнота сведений вызывает повторное обращение к инициатору и удлиняет реакцию на заявку.
## 1.2 Сравнение существующих решений
Для автоматизации процесса рассматривались три варианта: универсальная система управления обслуживанием, модуль в составе используемой на предприятии учётной системы и собственная разработка. Критериями сравнения выбраны стоимость владения, возможность интеграции со справочником оборудования и трудоёмкость внедрения [1].
Результаты сравнения сведены в @Таблица:tab_cmp.
%tab_cmp Сравнение вариантов автоматизации процесса
| Вариант | Стоимость владения | Интеграция со справочником | Трудоёмкость внедрения |
|---------|--------------------|----------------------------|------------------------|
| Универсальная система обслуживания | высокая | через файловый обмен | средняя |
| Модуль учётной системы | средняя | штатная | высокая |
| Собственная разработка | низкая | по REST | низкая |
Универсальная система покрывает больше сценариев, чем требуется подразделению, и вносит внешний файловый обмен, который сам становится источником расхождений [2]. Модуль учётной системы обеспечивает штатную интеграцию, но его доработка требует привлечения поставщика. Собственная разработка выбрана как вариант, закрывающий требования при наименьшей трудоёмкости.
## 1.3 Требования к модулю
Требования сгруппированы по категориям и приведены в @Таблица:tab_req. Формулировки нефункциональных требований опираются на рекомендации по описанию качества программных систем [3].
%tab_req Требования к модулю учёта заявок
| Категория | Требование |
|-----------|------------|
| Функциональные | регистрация заявки с привязкой к единице оборудования |
| ^ | назначение исполнителя и контроль срока |
| ^ | хранение истории обслуживания единицы оборудования |
| Производительность | обработка 100 заявок в час при 20 одновременных пользователях |
| ^ | время отклика интерфейса не более 2 с |
| Надёжность | доступность не ниже 99,5 % в рабочие часы |
| Интеграция | получение справочника оборудования по REST |
Ограничения проекта: развёртывание в контуре предприятия, единая аутентификация через корпоративную службу, хранение данных не менее трёх лет.
# 2 Проектирование модуля
## 2.1 Архитектура модуля
Модуль спроектирован по трёхуровневой схеме: клиентское приложение, сервис прикладной логики и хранилище. Такое разделение позволяет обновлять правила обработки заявок без изменения клиента [4].
Контейнерная структура модуля приведена на @Рисунок:c4_containers.
%c4_containers Контейнеры модуля учёта заявок +landscape
```uml-c4
Person(dispatcher, "Диспетчер", "Регистрирует и распределяет заявки")
Person(worker, "Исполнитель", "Выполняет работы по заявке")
System_Boundary(app, "Модуль учёта заявок") {
Container(spa, "Веб-клиент", "React", "Интерфейс диспетчера и исполнителя")
Container(api, "Сервис заявок", "FastAPI", "Правила обработки и контроль сроков")
ContainerDb(db, "Хранилище заявок", "PostgreSQL", "Заявки, работы, история")
}
System_Ext(equip, "Справочник оборудования", "Учётная система предприятия")
System_Ext(sso, "Корпоративная служба входа", "Единая аутентификация")
Rel(dispatcher, spa, "Регистрирует заявки", "HTTPS")
Rel(worker, spa, "Отмечает выполнение", "HTTPS")
Rel(spa, api, "Вызывает методы", "REST/JSON")
Rel(api, db, "Читает и пишет", "SQL")
Rel(api, equip, "Запрашивает единицы оборудования", "REST")
Rel(spa, sso, "Аутентифицирует пользователя", "OIDC")
```
Справочник оборудования остаётся во внешней учётной системе: дублирование его в модуле привело бы к расхождению данных при выводе оборудования из эксплуатации.
## 2.2 Модель данных
Логическая модель данных охватывает три сущности: заявку, работу по заявке и запись истории обслуживания. Единица оборудования в модуле не хранится, вместо неё сохраняется её идентификатор во внешнем справочнике.
Модель данных приведена на @Рисунок:erd.
%erd Логическая модель данных модуля
```uml
@startuml
hide circle
skinparam linetype ortho
entity "Заявка" as request {
* id : bigint <<PK>>
--
* equipment_ref : varchar(32)
* created_at : timestamp
* due_at : timestamp
* status : varchar(16)
description : text
}
entity "Работа" as work {
* id : bigint <<PK>>
--
* request_id : bigint <<FK>>
* performer : varchar(128)
* started_at : timestamp
finished_at : timestamp
}
entity "Запись истории" as history {
* id : bigint <<PK>>
--
* request_id : bigint <<FK>>
* changed_at : timestamp
* old_status : varchar(16)
* new_status : varchar(16)
}
request ||--o{ work
request ||--o{ history
@enduml
```
Статус заявки хранится строкой из фиксированного набора значений, а не ссылкой на справочник: набор состояний определяется регламентом обслуживания и меняется вместе с версией модуля.
## 2.3 Оценка объёма хранилища
Объём данных за период эксплуатации оценивается произведением числа записей на средний размер записи с учётом коэффициента служебных структур базы данных [5].
%eq_volume
$$
V = N \cdot S \cdot k
$$
где $N$ — число заявок за период; $S$ — средний размер записи вместе со связанными работами и историей, байт; $k$ — коэффициент накладных расходов хранилища.
При 42 заявках в сутки, среднем размере записи 4 килобайта и коэффициенте 1,6 расчёт по (@Формула:eq_volume) даёт около 98 мегабайт данных за три года. Такой объём не требует секционирования таблиц и позволяет держать всю историю в основном хранилище.
# 3 Реализация ключевых функций
## 3.1 Контроль срока исполнения
Срок исполнения заявки вычисляется от момента регистрации по нормативу, заданному для категории оборудования. Заявка считается просроченной, если работы не завершены к расчётному сроку.
Реализация проверки приведена в @Листинг:code_overdue.
%code_overdue Проверка просроченных заявок
```python
from datetime import datetime, timedelta
NORMS_HOURS = {'critical': 4, 'standard': 24, 'planned': 72}
def due_at(created_at: datetime, category: str) -> datetime:
return created_at + timedelta(hours=NORMS_HOURS[category])
def is_overdue(request: dict, now: datetime) -> bool:
if request['status'] == 'closed':
return False
return now > due_at(request['created_at'], request['category'])
```
Нормативы вынесены в отдельную структуру: их изменение регламентом не требует правки логики проверки.
## 3.2 Проверка полноты сведений при регистрации
Доля обращений с неполными сведениями об оборудовании составляла 18 %, поэтому регистрация заявки блокируется до получения идентификатора единицы оборудования из внешнего справочника. Обращение к справочнику выполняется при вводе, а не при сохранении: диспетчер видит ошибку до того, как заполнит остальные поля.
Проверка вернула долю отклонённых при вводе форм на уровне 4 % от общего числа регистраций, остальные обращения были дополнены сведениями сразу.
# *ЗАКЛЮЧЕНИЕ
Проанализирован процесс приёма и исполнения заявок на техническое обслуживание: в нём участвуют три роли, а основной потерей времени является уточнение сведений об оборудовании, затрагивающее почти каждое пятое обращение.
Сформированы требования к модулю и выбран вариант собственной разработки — он закрывает требования подразделения при наименьшей трудоёмкости внедрения и позволяет получать справочник оборудования по REST вместо файлового обмена.
Модуль спроектирован по трёхуровневой схеме; модель данных содержит заявку, работу и запись истории, а справочник оборудования остаётся во внешней системе. Оценка объёма хранилища за три года эксплуатации составила около 98 мегабайт, что не требует секционирования таблиц.
Реализованы контроль срока исполнения с нормативами по категориям оборудования и проверка полноты сведений на этапе ввода: доля неполных обращений снизилась с 18 % до 4 %.
# *СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
[1]: Ричардс М., Форд Н. Фундаментальный подход к программной архитектуре: паттерны, свойства, проверенные методы. — СПб.: Питер, 2023. — 432 с.
[2]: Клеппман М. Высоконагруженные приложения: программирование, масштабирование, поддержка. — СПб.: Питер, 2022. — 640 с.
[3]: ГОСТ Р ИСО/МЭК 25010-2015. Информационные технологии. Системная и программная инженерия. Требования и оценка качества систем и программного обеспечения. — М.: Стандартинформ, 2022. — 36 с.
[4]: Ньюмен С. От монолита к микросервисам. — М.: ДМК Пресс, 2022. — 274 с.
[5]: Документация PostgreSQL 16. Раздел «Database Physical Storage». — URL: https://www.postgresql.org/docs/16/storage.html (дата обращения: 14.02.2026).
[6]: Кириллина Ю. В. и др. Методические указания по оформлению учебных работ. — М.: РТУ МИРЭА, 2022. — 64 с.
# *ПРИЛОЖЕНИЯ
Приложение А — Схема состояний заявки
Приложение Б — Фрагмент сценария регистрации заявки
## Приложение А Схема состояний заявки
Переходы между состояниями заявки приведены на @Рисунок:state_req. Требования к оформлению схемы приняты по методическим указаниям [6].
%state_req Состояния заявки на обслуживание
```uml
@startuml
[*] --> Новая
Новая --> Назначена : назначен исполнитель
Назначена --> ВРаботе : работы начаты
ВРаботе --> Закрыта : работы завершены
Назначена --> Отклонена : обращение неправомерно
Новая --> Отклонена : обращение неправомерно
Закрыта --> [*]
Отклонена --> [*]
@enduml
```
## Приложение Б Фрагмент сценария регистрации заявки
Последовательность обращений при регистрации заявки приведена на @Рисунок:seq_reg.
%seq_reg Последовательность регистрации заявки
```uml
@startuml
autonumber
actor Диспетчер as d
participant "Веб-клиент" as spa
participant "Сервис заявок" as api
participant "Справочник оборудования" as equip
database "Хранилище" as db
d -> spa : вводит идентификатор оборудования
spa -> api : GET /equipment/{ref}
api -> equip : GET /units/{ref}
equip --> api : сведения об оборудовании
api --> spa : карточка оборудования
d -> spa : заполняет описание неисправности
spa -> api : POST /requests
api -> db : INSERT request
db --> api : идентификатор заявки
api --> spa : номер заявки и срок исполнения
@enduml
```
+224
View File
@@ -0,0 +1,224 @@
# *СОДЕРЖАНИЕ
[TOC]
# Практическая работа №1. Описание предметной области и границ системы
## Цель работы
Описать предметную область складского учёта, выделить участников процесса и зафиксировать границы автоматизируемой системы.
## Ход работы
Рассматривается склад готовой продукции среднего предприятия: три зоны комплектации, один участок приёмки, две смены по четыре кладовщика. Через склад проходит около 400 отгрузок в сутки, приёмка занимает от 20 до 90 минут на партию.
Участники процесса и их задачи приведены в @Таблица:pr1_roles.
%pr1_roles Участники процесса складского учёта
| Участник | Задача | Что получает на выходе |
|----------|--------|------------------------|
| Кладовщик приёмки | сверяет поступившую партию с накладной | акт приёмки |
| Комплектовщик | собирает заказ по заданию | укомплектованный заказ |
| Кладовщик отгрузки | оформляет передачу заказа перевозчику | подписанная накладная |
| Начальник склада | контролирует остатки и сроки | сводка по остаткам |
Границы системы и её внешнее окружение показаны на @Рисунок:pr1_ctx.
%pr1_ctx Контекстная диаграмма потоков данных
```dfd
style context
entity Supplier Поставщик
entity Carrier Перевозчик
entity Sales Отдел продаж
process System Система складского учёта
Supplier --> System товарная накладная
Sales --> System заказ на отгрузку
System --> Carrier накладная на отгрузку
System --> Sales сведения об остатках
```
Границы приняты по участку от приёмки партии до передачи заказа перевозчику. Бухгалтерский учёт и закупки остаются за пределами системы: они ведутся в учётной системе предприятия и получают из системы только сводки.
## Выводы
Основным ограничением процесса является ручной ввод накладных при приёмке: он даёт до 6 % расхождений в учёте остатков и удлиняет приёмку партии в среднем на 25 минут. Именно этот участок определяет требования к системе.
# Практическая работа №2. Модель бизнес-процессов склада
## Цель работы
Построить функциональную модель процесса складского учёта в нотации IDEF0 и определить состав функций верхнего уровня.
## Ход работы
Контекстная диаграмма процесса приведена на @Рисунок:pr2_a0.
%pr2_a0 Контекстная диаграмма A-0
```idef0
title Обеспечить движение товара на складе
node A-0
number 1
project Система складского учёта
context TOP
[A0] Обеспечить движение товара на складе
<- Товарная накладная
<- Заказ на отгрузку
^ Регламент складских операций
-> Подписанная накладная на отгрузку
-> Сводка по остаткам
v Персонал склада
```
Декомпозиция функции верхнего уровня выделила три функции, приведённые на @Рисунок:pr2_a0d.
%pr2_a0d Декомпозиция A0
```idef0
title Обеспечить движение товара на складе
node A0
number 2
project Система складского учёта
context A-0
purpose Сократить расхождения учёта при приёмке и отгрузке
viewpoint Начальник склада
[A1] Принять партию
[A2] Разместить и хранить
[A3] Скомплектовать и отгрузить
A1 <- Товарная накладная [I1]
A3 <- Заказ на отгрузку [I2]
A1, A2, A3 ^ Регламент складских операций [C1]
A2 ^ Схема зонирования склада [C2]
A1 -> A2 : принятая партия
A2 -> A3 : товар к комплектации
A3 -> Подписанная накладная на отгрузку [O1]
A2 -> Сводка по остаткам [O2]
A1, A2, A3 v Персонал склада [M1]
A2 v Складское оборудование [M2]
```
Схема зонирования вынесена в управление, а не во вход: она задаёт правила размещения и не расходуется в процессе.
## Выводы
Функция размещения оказалась единственной, которая одновременно получает управление от схемы зонирования и формирует сводку по остаткам. Расхождения учёта возникают именно на переходе от приёмки к размещению, когда партия физически принята, но ещё не отражена в остатках.
# Практическая работа №3. Модель данных системы
## Цель работы
Спроектировать логическую модель данных системы складского учёта и обосновать состав сущностей.
## Ход работы
Модель данных приведена на @Рисунок:pr3_erd.
%pr3_erd Логическая модель данных системы
```uml
@startuml
hide circle
skinparam linetype ortho
entity "Партия" as batch {
* id : bigint <<PK>>
--
* supplier : varchar(255)
* accepted_at : timestamp
* invoice_no : varchar(32)
}
entity "Товарная позиция" as item {
* id : bigint <<PK>>
--
* batch_id : bigint <<FK>>
* sku : varchar(32)
* qty : numeric(12,3)
zone : varchar(16)
}
entity "Заказ на отгрузку" as order_ {
* id : bigint <<PK>>
--
* created_at : timestamp
* status : varchar(16)
}
entity "Строка заказа" as line {
* id : bigint <<PK>>
--
* order_id : bigint <<FK>>
* sku : varchar(32)
* qty : numeric(12,3)
}
batch ||--o{ item
order_ ||--o{ line
@enduml
```
Остаток по артикулу не хранится отдельным полем, а вычисляется как разность принятого и отгруженного количества. Такое решение исключает расхождение между остатком и первичными документами, но требует индекса по артикулу для приемлемой скорости выборки.
Соответствие сущностей модели функциям процесса приведено в @Таблица:pr3_map.
%pr3_map Соответствие сущностей функциям процесса
| Функция | Сущности | Что изменяется |
|---------|----------|----------------|
| Принять партию | Партия, Товарная позиция | добавляются позиции с нулевой зоной |
| Разместить и хранить | Товарная позиция | заполняется зона размещения |
| Скомплектовать и отгрузить | Заказ на отгрузку, Строка заказа | создаются строки и уменьшается доступное количество |
## Выводы
Модель обходится четырьмя сущностями за счёт вычисляемого остатка. Слабое место решения — скорость расчёта остатка при росте числа позиций: при объёме свыше миллиона строк потребуется материализованное представление.
# Практическая работа №4. Расчёт нагрузки на систему
## Цель работы
Оценить пиковую нагрузку на систему складского учёта и объём хранилища на три года эксплуатации.
## Ход работы
Пиковая интенсивность запросов оценивается по числу операций в смену с учётом коэффициента неравномерности.
%pr4_eq_load
$$
\lambda_{\max} = \frac{Q \cdot m}{T} \cdot k
$$
где $Q$ — число отгрузок в смену; $m$ — среднее число запросов на одну отгрузку; $T$ — длительность смены в секундах; $k$ — коэффициент неравномерности нагрузки.
Расчёт по (@Формула:pr4_eq_load) при 200 отгрузках в смену, 14 запросах на отгрузку, смене 12 часов и коэффициенте 2,5 даёт пиковую интенсивность около 0,16 запроса в секунду.
Реализация расчёта приведена в @Листинг:pr4_code.
%pr4_code Расчёт пиковой интенсивности запросов
```python
def peak_rate(shipments: int, requests_per_shipment: int,
shift_seconds: int, unevenness: float) -> float:
return shipments * requests_per_shipment / shift_seconds * unevenness
```
Результаты расчёта для трёх сценариев роста приведены в @Таблица:pr4_load.
%pr4_load Оценка нагрузки для сценариев роста
| Сценарий | Отгрузок в смену | Пиковая интенсивность, запр./с | Объём за три года, ГБ |
|----------|------------------|-------------------------------|-----------------------|
| Текущий | 200 | 0,16 | 1,4 |
| Рост на 50 % | 300 | 0,24 | 2,1 |
| Двукратный рост | 400 | 0,32 | 2,8 |
## Выводы
Даже при двукратном росте отгрузок пиковая интенсивность остаётся ниже одного запроса в секунду, поэтому одного экземпляра сервиса достаточно. Ограничивающим фактором становится не нагрузка, а расчёт остатков по накопленным первичным документам.