# *СОДЕРЖАНИЕ [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 <> -- * supplier : varchar(255) * accepted_at : timestamp * invoice_no : varchar(32) } entity "Товарная позиция" as item { * id : bigint <> -- * batch_id : bigint <> * sku : varchar(32) * qty : numeric(12,3) zone : varchar(16) } entity "Заказ на отгрузку" as order_ { * id : bigint <> -- * created_at : timestamp * status : varchar(16) } entity "Строка заказа" as line { * id : bigint <> -- * order_id : bigint <> * 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 | ## Выводы Даже при двукратном росте отгрузок пиковая интенсивность остаётся ниже одного запроса в секунду, поэтому одного экземпляра сервиса достаточно. Ограничивающим фактором становится не нагрузка, а расчёт остатков по накопленным первичным документам.