📄 Статьи

Пример ТЗ: модуль «Курс валют в подвале сайта»

Клиент часто говорит: «Я не понимаю, что такое ТЗ и зачем оно нужно. Просто скажите, сколько это будет стоить».

Я показываю реальный пример технического задания на небольшой модуль — чтобы вы видели, за что платите.

Модуль ОЧЕНЬ простой: вывод курса валют в подвале сайта на Laravel. Но он показывает весь цикл: от архитектуры до распределения задач между командой.

Время на разработку написано "примерно": это лишь демонстрация. Фактически решается за 2 часа максимум.

Задачи исполнителям описаны кратко. Набор задач - полная декомпозиция (отдельная опция). В условиях создания реального ТЗ описание в задачах как правило более полное.

ТЗ приведено с учетом специалистов: бэкенд-разработчик, фронтенд-разработчик, системный администратор, тестировщик.

Коммуникация между специалистами
Формат данных от API? → Бэкенд (проверяет документацию)
Как выглядит плашка? → Фронтенд (согласовывает с заказчиком)
Какая дата «обновлено»? → Бэкенд (использует rate_date из API)
Как часто обновлять? → Бэкенд (настраивает расписание)

Техническое задание

модуль «Курс валют в подвале сайта»

Заказчик: _______________   |   Исполнитель: _______________   |   Дата: _______________   |   Версия: 1.0

1. Цель

Реализовать отображение актуальных курсов валют (USD, EUR) в подвале сайта с автоматическим обновлением данных.

2. Требования к функциональности

Модуль должен выводить курсы USD и EUR к рублю в подвале сайта на всех страницах. Отображение — в формате «USD: 92.50 ₽» и «EUR: 98.20 ₽». Рядом с курсами выводится дата последнего обновления, например: «Курс на 12.06.2025».

Источник данных — внешний API (exchangerate-api.com или ЦБ РФ, выбор согласовывается с Заказчиком). Данные обновляются автоматически один раз в сутки по расписанию (Cron). Если API недоступен, модуль должен отображать последние сохранённые данные, а ошибку записать в лог.

3. Архитектура

Модуль строится на стандартных компонентах Laravel. Для хранения данных создаётся таблица exchange_rates с полями: id, currency_code, rate, rate_date, created_at. Модель ExchangeRate обеспечивает доступ к данным. Сервис ExchangeRateService отвечает за получение данных из API и обновление таблицы. Для автоматического обновления создаётся Artisan-команда exchange:update, которая вызывается через Cron.

Вывод в подвале реализуется через View Composer, который передаёт данные в шаблон подвала. Вёрстка плашки — адаптивная, под стиль сайта.

4. Требования к данным

В системе хранятся курсы только двух валют — USD и EUR. Курсы сохраняются с точностью до двух знаков после запятой. Дата обновления фиксируется автоматически при каждом успешном обновлении. В случае, если API не отвечает, модуль продолжает использовать последние успешно сохранённые значения — это позволяет сайту оставаться работоспособным даже при внештатных ситуациях.

5. Интерфейсные требования

Плашка с курсами располагается в подвале сайта и видна на всех страницах. Вывод выполняется в одну строку: «USD: 92.50 ₽ | EUR: 98.20 ₽ | обновлено: 12.06.2025». Вёрстка должна корректно отображаться на мобильных устройствах, не нарушая общую структуру подвала.

6. Требования к производительности

Загрузка страницы не должна замедляться из-за работы модуля. Данные для отображения берутся из базы данных, а не из внешнего API при каждом запросе — это исключает задержки, связанные с сетью. Запрос к базе данных должен быть минимальным: один простой SELECT без JOIN-ов. Обновление данных происходит один раз в сутки, что не создаёт лишней нагрузки ни на БД, ни на внешний сервис.

7. Технические требования

Модуль разрабатывается на текущей версии Laravel, используемой в проекте. База данных — MySQL. Код должен быть написан на PHP 7.4 или выше. Для управления расписанием используется встроенный планировщик Laravel (Scheduler). Все ошибки, связанные с обновлением данных, записываются в стандартный Laravel-лог. Внешний API выбирается по согласованию с Заказчиком.

8. Ограничения (что НЕ входит в ТЗ)

В данный модуль не входит автоматическое уведомление о недоступности API, построение графиков курсов, вывод курсов в других частях сайта (кроме подвала), интеграция с биржевыми данными или другими валютами, настройка перечня валют через админку, а также хранение истории изменений курсов. Все эти функции могут быть реализованы отдельными модулями в будущем при необходимости.

9. Критерии приёмки

Результат работы считается принятым, если курсы отображаются в подвале на всех страницах, обновляются автоматически ежедневно в 10:00, а при недоступности API показываются последние сохранённые данные. Также проверяется наличие даты обновления, корректное отображение на мобильных устройствах, логирование ошибок и отсутствие замедления загрузки страницы более чем на 5% относительно текущих показателей.

10. Риски

Основной риск — изменение формата ответа внешнего API. Для минимизации этого риска в сервисе предусматривается проверка структуры ответа и fallback-механизм для сохранения работоспособности при изменении формата. Второй риск — недоступность API или проблемы с доступом к сети. В этом случае модуль продолжает работать на последних актуальных данных, а ошибка фиксируется в логах для последующего анализа.

11. Сроки

Оценка времени выполнения — 4.5 рабочих дня. Создание таблицы, модели и сервиса занимает полтора дня. Разработка Artisan-команды и настройка расписания — ещё полдня. Фронтенд-часть (View Composer, вёрстка плашки, адаптивность) — один день. Настройка Cron на сервере и проверка доступности API — полдня. И ещё один день выделяется на тестирование всех сценариев, включая падение API, и доработку по результатам тестирования.

12. Приложения

Подписи:

Заказчик: __________________ / ______________________

Исполнитель: __________________ / ______________________

# Распределение задач по исполнителям

Бэкенд 1 день  |  Фронтенд 1 день (параллельно)  |  Сисадмин 15 мин  |  QA 0.5 дня
Бэкенд-разработчик
#TZ-01 Бэкенд Создать таблицу exchange_rates
Для чего: Хранить курсы валют с возможностью быстрого доступа к актуальным и историческим данным.
Что сделать: Создать таблицу в MySQL. Добавить индексы для быстрого поиска по валюте и дате.
CREATE TABLE exchange_rates ( id INT PRIMARY KEY AUTO_INCREMENT, currency_code VARCHAR(10) NOT NULL, rate DECIMAL(12,4) NOT NULL, rate_date DATE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, INDEX idx_currency_date (currency_code, rate_date) );
На выходе: Таблица создана, индексы добавлены.
#TZ-02 Бэкенд Создать модель ExchangeRate
Для чего: Доступ к данным таблицы через ORM (Eloquent).
Что сделать: Создать модель с указанием таблицы, заполняемых полей и отключением автоматических timestamps.
На выходе: Модель создана. Проверить через tinker.
#TZ-03 Бэкенд Создать сервис для работы с API
Для чего: Централизовать логику получения данных из API и сохранения в БД.
Что сделать: Создать класс ExchangeRateService с методами updateRates() и getCurrentRates(). Использовать HTTP Client. Предусмотреть логирование ошибок и удаление записей старше 30 дней.
На выходе: Данные сохраняются в таблицу, логируются ошибки.
#TZ-04 Бэкенд Создать Artisan-команду exchange:update
Для чего: Запуск обновления вручную и по расписанию.
Что сделать: Создать команду, которая вызывает updateRates(), выводит сообщение в консоль и возвращает код выхода.
На выходе: Команда работает, данные обновляются.
#TZ-05 Бэкенд Настроить расписание обновления
Для чего: Автоматическое обновление раз в сутки.
Что сделать: В Kernel.php добавить schedule->command('exchange:update')->dailyAt('10:00').
На выходе: Расписание добавлено.
#TZ-06 Бэкенд Документация для сисадмина
Для чего: Чтобы сисадмин мог настроить Cron.
Что сделать: Описать команду для Cron, пользователя и способ проверки.
На выходе: Документация передана.
Фронтенд-разработчик / Верстальщик
#TZ-07 Фронтенд Создать View Composer
Для чего: Передавать данные о курсах в шаблон подвала.
Что сделать: Создать ExchangeRateComposer и зарегистрировать в AppServiceProvider.
На выходе: В шаблон подвала передаётся $exchangeRates.
#TZ-08 Фронтенд Шаблон вывода курсов
Для чего: Отображать курсы в нужном формате.
Что сделать: Добавить в footer.blade.php вывод курсов и даты обновления.
На выходе: Курсы отображаются в подвале.
#TZ-09 Фронтенд Вёрстка плашки
Для чего: Аккуратное отображение на всех устройствах.
Что сделать: HTML-разметка и CSS (адаптив, дата обновления — серым шрифтом).
На выходе: Плашка корректно отображается на всех устройствах.
#TZ-10 Фронтенд Интеграция в подвал
Для чего: Чтобы плашка стала частью структуры сайта.
Что сделать: Вставить плашку в существующий шаблон подвала.
На выходе: Плашка на всех страницах, без нарушения вёрстки.
Системный администратор
#TZ-11 Сисадмин Настроить Cron
Для чего: Чтобы команда выполнялась автоматически.
Что сделать: Добавить в Cron строку для schedule:run.
* * * * * www-data cd /var/www/your-project && php artisan schedule:run >> /dev/null 2>&1
На выходе: Cron настроен, задача выполняется.
#TZ-12 Сисадмин Проверить доступ к API
Для чего: Убедиться, что сервер может обращаться к внешнему API.
Что сделать: Проверить через curl, при необходимости открыть доступ в фаерволе или добавить API-ключ в .env.
На выходе: API доступно с сервера.
Тестировщик (QA)
#TZ-13 QA Проверить функциональность
Для чего: Убедиться, что модуль работает по ТЗ.
Что сделать: Проверить отображение, обновление, поведение при падении API.
На выходе: Все сценарии работают. Ошибки логируются.
#TZ-14 QA Проверить вёрстку
Для чего: Убедиться в корректном отображении на всех устройствах.
Что сделать: Проверить десктоп, планшет, мобильный. Плашка не должна «ломать» вёрстку.
На выходе: Плашка корректно отображается на всех устройствах.
#TZ-15 QA Проверить производительность
Для чего: Убедиться, что модуль не замедляет загрузку страниц.
Что сделать: Замерить время загрузки с плашкой и без неё. Отклонение ≤ 5%.
На выходе: Отчёт о замерах. Производительность в норме.
📄 Статьи