Рабочий лист: Организация интерфейса с пользователем: ввод

Практическое закрепление темы 4 (§2.2 с.7–8 учебной программы): проектирование компоновки экранных форм ввода данных в реляционную СУБД, маппинг элементов управления (Masked Input, Combobox/Select, RadioGroup, Checkbox, DatePicker, Master-Detail Grid) на атрибуты таблиц, обеспечение эргономики UI и транзакционной целостности данных.

Выберите назначенный вариант кейса:

Вариант 1. Регистрация нового заказа в CRM-системе оптовых продаж (Master-Detail)

Контекст предметной области: В корпоративной CRM оптовой компании менеджер оформляет заказ клиента. Документ строится по иерархическому шаблону Master-Detail:

  • Шапка заказа (Master): Номер заказа, Дата заказа, Выбор клиента из выпадающего справочника (Combobox), Склад отгрузки (Combobox), Способ доставки, Примечание.
  • Табличная часть спецификации (Detail Grid): Динамическая таблица строк заказа: Выбор товара (Combobox с поиском), Количество (числовое поле с валидацией > 0), Базовая цена (руб), Скидка (%), Автоматически рассчитываемая сумма строки. Кнопки добавления и удаления позиций.
  • Итоги: Автоматический подсчет итоговой суммы документа, блокировка кнопки сохранения от повторного нажатия.

Реляционные таблицы СУБД:

CREATE TABLE wholesale_orders (
    order_id BIGSERIAL PRIMARY KEY,
    order_number VARCHAR(30) NOT NULL UNIQUE,
    client_id INT NOT NULL REFERENCES clients(id),
    warehouse_id INT NOT NULL REFERENCES warehouses(id),
    order_date DATE NOT NULL,
    total_amount NUMERIC(14,2) NOT NULL DEFAULT 0,
    status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'confirmed', 'shipped', 'cancelled'))
);

CREATE TABLE wholesale_order_items (
    item_id BIGSERIAL PRIMARY KEY,
    order_id BIGINT NOT NULL REFERENCES wholesale_orders(order_id) ON DELETE CASCADE,
    product_id INT NOT NULL REFERENCES products(id),
    quantity NUMERIC(10,3) NOT NULL CHECK (quantity > 0),
    unit_price NUMERIC(12,2) NOT NULL CHECK (unit_price >= 0),
    discount_percent NUMERIC(5,2) NOT NULL DEFAULT 0 CHECK (discount_percent BETWEEN 0 AND 100),
    line_total NUMERIC(14,2) NOT NULL CHECK (line_total >= 0)
);

Задание 1.1. Эскиз и правила компоновки экранной формы

Опишите логическую структуру формы, взаимное расположение шапки (Master) и спецификации (Detail), порядок обхода фокуса (Tab Order) и действия кнопок управления.

Задание 1.2. Спецификация элементов управления и матрица маппинга на атрибуты БД

Для каждого элемента формы укажите: тип контрола UI, привязку к колонке таблицы, разделение Display Member / Value Member (для внешних ключей) и правила валидации.

Задание 1.3. Транзакционный JSON DTO и алгоритм серверного сохранения

Приведите пример JSON-пакета (DTO), отправляемого формой при клике «Сохранить», и транзакционный SQL-скрипт (BEGIN ... COMMIT), гарантирующий неделимость сохранения шапки и всех позиций.

Задание 1.4. Вопросы самопроверки и эргономики UI

1. Почему сохранение каждой строки заказа отдельным AJAX-запросом без транзакции недопустимо?
2. Как в выпадающем списке клиентов отделить видимое наименование компании от ID внешнего ключа?

Вариант 2. Экранная форма оформления путевого листа АТП

Контекст предметной области: Диспетчер автотранспортного предприятия (АТП) оформляет путевой лист грузового автомобиля перед выездом на рейс и регистрирует показания при возвращении в автопарк:

  • Реквизиты рейса: Номер путевого листа (текстовое поле с маской), Автомобиль (выпадающий список с указанием госномера и марки), Водитель (выпадающий список с табельным номером и ФИО), Маршрут (Combobox / текстовое поле).
  • Временные параметры: Дата и время планового выезда и возврата (компонент DateTimePicker в стандарте ISO 8601).
  • Показания спидометра (одометра): Показания при выезде (км) и показания при возврате (км). Валидация: показания возврата строго больше показаний выезда. Расчет пробега за смену.
  • Служебные отметки: Флажок (Checkbox) «Медосмотр пройден», флажок «Техконтроль пройден».

Реляционная таблица СУБД:

CREATE TABLE waybills (
    waybill_id BIGSERIAL PRIMARY KEY,
    waybill_code VARCHAR(25) NOT NULL UNIQUE,          -- Маска: ПЛ-9999-9999
    vehicle_id INT NOT NULL REFERENCES vehicles(id),
    driver_id INT NOT NULL REFERENCES drivers(id),
    route_id INT NOT NULL REFERENCES routes(id),
    departure_time TIMESTAMP WITH TIME ZONE NOT NULL,
    return_time TIMESTAMP WITH TIME ZONE,
    odometer_start INT NOT NULL CHECK (odometer_start >= 0),
    odometer_end INT CHECK (odometer_end >= odometer_start),
    medical_check_passed BOOLEAN NOT NULL DEFAULT FALSE,
    technical_check_passed BOOLEAN NOT NULL DEFAULT FALSE,
    status VARCHAR(15) NOT NULL DEFAULT 'open' CHECK (status IN ('open', 'completed', 'cancelled')),
    CONSTRAINT chk_time CHECK (return_time IS NULL OR return_time > departure_time)
);

Задание 2.1. Эскиз и правила компоновки экранной формы

Опишите размещение блоков «Транспортное средство и водитель», «Хронометраж рейса», «Показания одометра и допуски». Укажите логику блокировки полей до закрытия смены.

Задание 2.2. Спецификация элементов управления и матрица маппинга на атрибуты БД

Составьте матрицу привязки контролов UI к колонкам waybills. Опишите маску ввода номера путевого листа, сопряжение DateTimePicker и чекбоксов допуска.

Задание 2.3. Алгоритм валидации одометра и времени рейса

Опишите двухуровневую валидацию: как UI в реальном времени подсвечивает ошибку, если одометр возврата меньше одометра выезда, и какое ограничение СУБД гарантирует целостность на сервере.

Задание 2.4. Вопросы самопроверки и эргономики UI

1. В каком формате компонент выбора даты обязан передавать значение на бэкенд, чтобы избежать ошибок региональных стандартов?
2. Почему при выборе автомобиля в Combobox необходимо отображать госномер вместе с гаражным номером?

Вариант 3. Форма госпитализации пациента в приемном отделении стационара

Контекст предметной области: В медицинской информационной системе (МИС) дежурный регистратор оформляет электронную историю болезни при экстренной или плановой госпитализации пациента:

  • Персональные данные пациента: ФИО пациента (поиск существующего в базе через Autocomplete или создание нового), СНИЛС (текстовое поле с маской 999-999-999 99), Дата рождения (DatePicker с ограничением ≤ сегодня), Пол (радиокнопки Муж/Жен).
  • Клинические параметры госпитализации: Отделение стационара (Combobox), Лечащий врач (связанный выпадающий список, фильтруемый по выбранному отделению), Тип госпитализации (Плановая / Экстренная через RadioGroup).
  • Диагноз при поступлении: Выбор кода и формулировки диагноза из клинического справочника МКБ-10 (международная классификация болезней) с механизмом контекстного автодополнения (Autocomplete / Typeahead) при вводе от 3 символов.
  • Служебные данные: Номер палаты, Согласие на обработку персональных данных (Checkbox NOT NULL).

Реляционные таблицы СУБД:

CREATE TABLE hospitalizations (
    hospitalization_id BIGSERIAL PRIMARY KEY,
    history_number VARCHAR(30) NOT NULL UNIQUE,        -- Номер истории болезни
    patient_id BIGINT NOT NULL REFERENCES patients(id),
    department_id INT NOT NULL REFERENCES departments(id),
    attending_doctor_id INT NOT NULL REFERENCES staff(id),
    admission_type VARCHAR(15) NOT NULL CHECK (admission_type IN ('emergency', 'planned')),
    icd10_code VARCHAR(10) NOT NULL REFERENCES icd10_catalog(code), -- Код МКБ-10
    admission_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
    ward_number VARCHAR(10),
    consent_signed BOOLEAN NOT NULL DEFAULT FALSE CHECK (consent_signed = TRUE),
    status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'discharged', 'transferred'))
);

Задание 3.1. Эскиз и правила компоновки экранной формы

Опишите компоновку формы: группировка карточки пациента, параметров отделения и диагноза. Укажите правила автофокуса и подсветку обязательных полей (* NOT NULL).

Задание 3.2. Спецификация элементов управления и матрица маппинга на атрибуты БД

Сформируйте матрицу соответствия контролов колонкам таблицы. Опишите архитектуру Autocomplete для 14 000 записей МКБ-10 (почему обычный <select> неприменим).

Задание 3.3. Каскадное связывание списков (Отделение → Врач)

Опишите логику работы зависимых элементов: как выбор значения в выпадающем списке «Отделение» динамически фильтрует список врачей в выпадающем списке «Лечащий врач».

Задание 3.4. Вопросы самопроверки и эргономики UI

1. Почему сохранение текстового названия диагноза вместо кода МКБ-10 нарушает требования нормализации базы данных?
2. Каким образом маска ввода для СНИЛС защищает базу данных от некорректных значений?

Вариант 4. Форма создания заявки на IT-поддержку (Service Desk)

Контекст предметной области: Корпоративный портал технической поддержки (Service Desk). Сотрудник организации отправляет электронный инцидент при возникновении сбоя ПО, оргтехники или сети:

  • Инициатор и рабочее место: ФИО заявителя (автоматически подставляется из сессии), Подразделение, Контактный телефон (поле с маской), Кабинет/Рабочее место (текстовое поле).
  • Категоризация инцидента: Категория проблемы (Combobox: «Рабочая станция», «Сетевое подключение», «1С / Корпоративное ПО», «Периферия/Принтеры»), Тема заявки (строка с ограничением длины).
  • Приоритет заявки (SLA): Группа радиокнопок (RadioGroup) с вариантами: «Низкий (Low)», «Средний (Medium)», «Высокий (High)», «Критический / Блокирующий (Critical)». Вариант по умолчанию: «Средний».
  • Описание и вложения: Многострочное текстовое поле (Textarea) с отображением счетчика оставшихся символов (до 2000 символов), Компонент прикрепления скриншотов с валидацией расширения (PNG, JPG, PDF, до 10 МБ).

Реляционные таблицы СУБД:

CREATE TABLE service_desk_tickets (
    ticket_id BIGSERIAL PRIMARY KEY,
    ticket_code VARCHAR(30) NOT NULL UNIQUE,          -- Например: INC-2026-00412
    requester_id INT NOT NULL REFERENCES employees(id),
    category_id INT NOT NULL REFERENCES ticket_categories(id),
    priority VARCHAR(15) NOT NULL DEFAULT 'medium' 
        CHECK (priority IN ('low', 'medium', 'high', 'critical')),
    subject VARCHAR(150) NOT NULL,
    description TEXT NOT NULL,
    room_number VARCHAR(20) NOT NULL,
    contact_phone VARCHAR(20) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'new' 
        CHECK (status IN ('new', 'in_progress', 'resolved', 'closed')),
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE TABLE ticket_attachments (
    attachment_id BIGSERIAL PRIMARY KEY,
    ticket_id BIGINT NOT NULL REFERENCES service_desk_tickets(ticket_id) ON DELETE CASCADE,
    file_name VARCHAR(255) NOT NULL,
    file_size_bytes INT NOT NULL CHECK (file_size_bytes <= 10485760), -- до 10 МБ
    mime_type VARCHAR(100) NOT NULL,
    storage_path VARCHAR(500) NOT NULL
);

Задание 4.1. Эскиз и правила компоновки экранной формы

Опишите структуру формы создания заявки. Обоснуйте использование RadioGroup для приоритета вместо обычного выпадающего списка (с точки зрения эргономики UI и скорости оценки инцидента).

Задание 4.2. Спецификация элементов управления и матрица маппинга на атрибуты БД

Составьте матрицу привязки контролов к таблицам service_desk_tickets и ticket_attachments. Укажите типы данных, ограничения NOT NULL и правила проверки файлов.

Задание 4.3. Ограничение длины текста и загрузка файлов

Опишите, как в UI реализуется счетчик символов для description, и каким образом файлы загружаются на сервер (сохранение пути storage_path в реляционную таблицу вместо хранения бинарных данных BLOB в основной строке).

Задание 4.4. Вопросы самопроверки и эргономики UI

1. Почему при создании инцидента поле приоритета обязано иметь значение по умолчанию (DEFAULT)?
2. Какая опасность возникает, если форма не блокирует кнопку «Отправить заявку» после первого нажатия?

✓ Данные успешно сохранены в LocalStorage!