Перейти к основному содержимому

Системная аналитика

Спроектировать мобильное приложение для покупки авиабилета

Необходимо описать:

  1. Бизнес-логику мобильного приложения (использовать любую удобную нотацию моделирования бизнес-процессов).
  2. Основные функции данного приложения (список должен быть составлен в порядке убывания важности функций для пользователя).
  3. Процесс синхронизации данных между клиентом и сервером (добавление и удаление списка избранного/любимых направлений, поиск/бронирование/оплата). Представить все в диаграммах, API методах и других представлениях.
  4. Подготовить прототип одного из экранов мобильного приложения и описать пользовательский интерфейс для данного экрана (например, покупка авиабилета).
  5. Подготовить подробное описание функции покупки авиабилета, которую можно было бы использовать в качестве постановки задачи для разработки (помимо текстового описания использовать UML диаграммы, указать используемые API методы, передаваемые и получаемые параметры, описать процесс хранения информации о заказах пользователя).
  6. Основные, на ваш взгляд, сложности разработки такого приложения. Вопросы, возникшие при выполнении тестового задания, которые вы бы задали заказчику.

Можно выбрать любой пункт и детализировать

к сведению

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

Прототип экранов мобильного приложения

Типовой экран

Экраны подсистемы покупки билетов будут построены по типовой схеме. Выделим три элемента, определим функции:

  • Верхняя панель инструментов (тулбар)
    • Заголовок страницы
    • Если конкретный экран является частью визарда, могут располагаться кнопки перехода на предыдущий этап
    • Контекстные кнопки. Например - отправить ссылку
  • Нижняя панель инструментов
    • Кнопка - перейти на следующий экран
    • Статистика с итогами заполнения формы текущего этапа. Например общая стоимость перелета и дополнительных услуг
  • Основной контейнер для приложения

Требования:

  • Верхняя панель инструментов прикреплена к верхней части экрана
  • Нижняя панель инструментов прикреплена к нижней части экрана
  • Контент панелей инструментов формируется таким образом, чтобы в данных контейнерах не было ни вертикального ни горизонтального скролла
  • Контент основной части экрана с содержимым визарда покупки билетов может иметь вертикальный скролл в зависимости от наполнения. Горизонтального скролла быть не должно.

Экран выбора тарифа для перелета

Открывается со списка вариантов перелета

Верхний тулбар

  • Кнопка "Назад" - возвращает на список вариантов перелета
  • Заголовок экрана - статический текст "Доступные тарифы"

Основное рабочее пространство

  • Виджет "Информация о перелете"
    • Статический текст. Дата и маршрут
    • Названия месяцев сокращаются по такому правилу янв., февр., апр., авг., сент., окт., нояб., дек. Такие названия месяцев, как март, май, июнь, июль, сокращений не имеют.
  • Виджеты с доступными тарифами
    • отрисовываются все объекты, которые вернул backend
    • Доступные тарифы отсортированы по цене в порядке возрастания
    • По умолчанию выбирается самый дешевый тариф - первый в списке
  • Виджет тарифа
    • Название - статический текст
    • Стоимость - показывается для всех не выбранных тарифов в виде разницы в стоимости тарифов относительно выбранного
    • Основные параметры тарифа - отрисовываются первые 4 опции тарифа из ответа бэкенда
    • Кнопка "Подробнее" - открывает попап в котором показаны все параметры тарифа, которые вернул бэкенд
    • Радиокнопка - индикатор выбора конкретного тарифа

Нижний тулбар

  • Стоимость выбранной опции . Формат <Итого: > {price}
  • Кнопка "Продолжить" - навигирует на Экран оформления заказа

Экран оформления заказа

Верхний тулбар

  • Кнопка "Назад" - возвращает экран выбора тарифа
  • Заголовок экрана - статический текст "Оформление заказа"

Основное рабочее пространство

  • Виджет информация о перелете

    • Статический текст. Дата и маршрут
      • Названия месяцев сокращаются по такому же правилу, что и в описании на экране выбора тарифов для перелета
      • Названия дней недели сокращаются как: Пн, Вт, Ср, Чт, Пт, Сб, Вс
      • Подробный билет - открывает попап с полными деталями выбранного варианта перелета и правилами тарифа
  • Секция "информация о покупателе"

    • Для пользователей, которые не вошли в приложение
      • Предложение войти в приложение
      • Поле ввода электронного адреса
        • Валидация корректности ввода адреса
      • Поле ввода номера телефонов
        • Подключается библиотека для валидации правильности ввода в зависимости от выбранной страны
    • Для пользователей которые вошли в приложение
      • В рамках публичной статьи проработка не предполагается
  • Секция "Информация о пассажире"

    • Счетчик числа выбранных пассажиров и статическое число предполагаемых к покупке билетов
    • Карточка пассажира
      • ФИО
      • Пол
      • дата рождения
      • номер паспорта
    • Кнопка "Новый пассажир" - инициирует сценарий добавления пассажира на форму оформления билета

Нижний тулбар

  • Кнопка "Продолжить"
    • Активна, если на форму добавлено необходимое число пассажиров
    • Навигирует на "Экран оформления заказа"

Описание функции покупки авиабилета

Основная задача раздела - показать артефакты системного аналитика - UML диаграммы, методы api, open-api спецификации, диаграмма последовательности хранения информации о заказах пользователя.

Предполагаемая системная архитектура

к сведению

Показанная выше системная архитектура для данного сценария использования не идеальная. Но достаточна для основной задачи статьи - показать артефакты аналитика.

Код диаграммы в нотации plunt uml C4
@startuml
!include C4_Container.puml
!define DEVICONS https://raw.githubusercontent.com/tupadr3/plantuml-icon-font-sprites/master/devicons
!include DEVICONS/go.puml
!include DEVICONS/react.puml
!include DEVICONS/mongodb.puml

'LAYOUT_TOP_DOWN()
'LAYOUT_AS_SKETCH()
LAYOUT_WITH_LEGEND()

title Пример подсистемы покупки билетов

Person(user_app, "Пользователь мобильного приложения", "бронирует авиабилеты")
Person(user_web, "Пользователь браузерной версии", "бронирует авиабилеты")


Boundary(booking_system, "Система бронирования билетов") {

'Микросервисы
Container(airtickets_frontend,"airtickets-frontend","react","Микрофронтенд для приложения Perfomance Management", $sprite="react")
Container(airticket_bff,"airtickets-bff","go","Взаимодействие с мобильным приложением и браузером пользователся", $sprite="go")
Container(airtickets_order_manager,"pm-integration-api","go","Интеграционный слой для взаимодействия с внешними системами", $sprite="go")
Container(ext_gds_amadeus_api,"ext-gds-amadeus-api", "go", "Взаимодействие с Amadeus GDS", $sprite="go")


'Базы данных
ContainerDb(airtickets_order_manager_db,"airtickets-order-manager-db","MongoDB","", $sprite="mongodb")
ContainerDb(ext_gds_amadeus_api_db,"ext-gds-amadeus-api-db","MongoDB","", $sprite="mongodb")


}

System_Ext(gds_amadeus, "Amadeus GDS", "Глобальная дистрибьюторская система")
System_Ext(platform_payment, "User payment", "Управление расчетами с пользователями и поставщиками")



'Взаимодействие пользователя и системы
Rel(user_web, airtickets_frontend,"забирает js, css файлы для сборки UI в браузере")
Rel(user_web, airticket_bff,"браузер забирает данные для последующей отрисовки в UI")
Rel(user_app, airticket_bff,"мобильное приложение забирает данные для последующей отрисовки в UI")



'взаимодействие между микросервисами внутри приложения
Rel(airtickets_order_manager, ext_gds_amadeus_api, "запросы цен и заказы", "gRPC")



'Взаимодействие api c базами данных
Rel(airtickets_order_manager, airtickets_order_manager_db, "Заказы пользователей")
Rel(ext_gds_amadeus_api, ext_gds_amadeus_api_db, "интеграционный вызовы во внешнюю систему")



'Внешние интеграции
Rel_L(ext_gds_amadeus_api, gds_amadeus, "Бронирование билетов", "http")
Rel_L(airtickets_order_manager, platform_payment, "Прием оплаты за заказы", "gRPC")


'bff
Rel(airticket_bff, airtickets_order_manager, "управление заказами", "gRPC")



'skinparam nodesep 100
'skinparam Linetype ortho




@enduml

Микросервисы и базы данных домена покупки билетов

  • airtickets-frontend : Микрофронтенд на react для web версии. Предоставляет js,css файлы для сборки страницы в браузере.
  • airtickets-bff : bff слой для организации взаимодействия с мобильными приложениями разных платформ и web браузерами. Пишет аудитные логи, взаимодействует с платформенным сервисом IAM для проверки прав пользователя на доступ к ресурсам.
  • airtickets-order-manager : сервис хранения заказов и оркестрации исполнения заказов. Имеет свою базу данных airtickets_order_manager_db а также встроенный движок управления процессами
  • ext-gds-amadeus-api : микросервис интеграции с конкретной GDS у которой может быть своя специфика обработки интеграционных вызовов

Внешние системы

  • Amadeus GDS : Система бронирования билетов
  • User payment : Платформенный сервис приема оплат. Считаем внешним, так как разрабатывается другой командой

Use-case

Наименование: Покупка авиабилета
Описание: Пользователь выбрал нужный авиабилет в результатах поиска и совершил покупку
Акторы : Пользователь
Другие участники : мобильное приложение пользователя; микросервисы подсистемы покупки билетов; шлюз оплаты; внешняя система бронирования Amadeus
Предусловия : Пользователь не авторизован в системе. Пользователь нашел в результатах поиска подходящий маршрут. Маршрут в поиске был предоставлен провайдером GDS Amadeus
Постусловия : пользователь купил билет; получен платеж от пользователя; билет направлен на электронный адрес покупателя; заведена задача на оплату заказа для системы бронирования

Основной сценарий

  1. Пользователь кликает на карточку маршрута в результатах поиска
  2. Мобильное приложение параллельно отправляет 3 запроса: 1 проверка наличия мест и стоимости /ConfirmFare ; 2 запрос условий перевозки /GetConditionData ; 3 запрос списка дополнительных сервисов /GetServicesAvailability. И показывает заглушку - ожидание ответа от бэкенда
  3. Микросервис airtickets-bff валидирует запросы и перенаправляет на микросервис airtickets-order-manager
  4. airtickets-order-manager регистрирует у себя 1 заказ, определяет поставщика маршрута и перенаправляет входящие запросы на интеграционный сервис ext-gds-amadeus-api
  5. ext-gds-amadeus-api логирует полученные запросы в своей базе данных и перенаправляет во внешнюю систему вызов /shopping/flight-offers/pricing
  6. Полученный ответ перенаправляется в airtickets-order-manager
  7. airtickets-order-manager пишет ответ в свою базу и отвечает на исходные запросы мобильного приложения
  8. Мобильное приложение отрисовывает "экран выбора тарифа для перелета"
  9. Пользователь выбирает опцию и нажимает кнопку "Продолжить" в нижнем тулбаре мобильного приложения
  10. Мобильное приложение открывает экран оформления заказа
  11. Пользователь заполняет данные на форме
    • email покупателя
    • данные пассажиров - ФИО, пол, дата рождения, номер паспорта
    • дополнительные сервисы
  12. Пользователь нажимает кнопку "Продолжить" в нижнем тулбаре мобильного приложения
  13. Мобильное приложение навигирует на экран подтвержения заказа и оплаты
  14. Пользователь вводит информацию об оплате в виджет платежного терминала и нажимает оплатить
  15. Мобильное приложение оправляет факт оплаты в бэкенд подсистемы покупки билетов и шлюза оплаты
  16. После подтверждения оплаты мобильное приложение сообщает о необходимости немного подождать выпуска билетов
  17. airtickets-order-manager переводит заказ в статус - ожидание оплаты
  18. Платежная система отправляет нотификацию о факте оплаты airtickets-order-manager
  19. airtickets-order-manager переводит заказ в статус оплачено и производит заказ в GDS Amadeus
  20. После подтверждения заказа и получения билетов airtickets-order-manager меняюет статус заказа на выполнено и перенаправляет билеты через платформенный сервис нотификаций

Диаграмма последовательности

Описание методов API

Показаны два примера: текстовый формат описания и описание в виде open api спецификации

Текстовый формат

запрос на подтверждение стоимости перевозки
Метод: Get /ConfirmFare2
Path parameters: не используются
Query parameters:

  • id (number) : ключ идемпотентности
  • supplier (text) : идентификатор поставщика
  • route_id (text) : id маршрута
  • timestamp (number) : unix timestamp запроса
  • currency (text) : кода валюты

Status Codes:

  • 200 OK : A successful response.

Response JSON Object:

  • .TripTimeChanged (boolean) : проставляется статус если время изменено относительно исходного запроса
  • .NotConfirmedSegmentNumbers (object) : список не подтвержденных сегментов
  • .TripsWithChangedTime (string) : список сегментов с измененным временем
  • .RequestId (number) : идентификатор запроса
  • .Price (string) : конкатенация кода валюты и стоимости маршрута
  • .FareId (number) : идентификатор маршрута
  • .Segments (string) : список сегментов
  • .Error (string) : код и текст ошибки
  • .Sign (string) : токен подписи запроса
  • .Confirmed (boolean) : факт подтверждения маршрута
  • .CheckMinConnectionTimeResult
  • .CheckMinConnectionTimeResult.NextDirectionIndex
  • .CheckMinConnectionTimeResult.ExpectedMinConnectionTime
  • .CheckMinConnectionTimeResult.ActualConnectionTime
  • .CheckMinConnectionTimeResult.Error
  • .CheckMinConnectionTimeResult.PreviousDirectionIndex
  • .PriceChangeInfo (string)

Пример ответа:

{
"Confirmed": true,
"FareId": "4305",
"Price": "RUB12012",
"RequestId": "75055675067185",
"Segments": "SVO0915N35042011E1305AER-AER0845D335P6950E1220SVO",
"Sign": "EF09ED35DB3D2E94DE244A024BD1516360CC9E1B1F6189399A0004C0FC10DDA9",
"PriceChangeInfo": null,
"NotConfirmedSegmentNumbers": [],
"TripTimeChanged": false,
"TripsWithChangedTime": null,
"CheckMinConnectionTimeResult": {
"Error": null,
"ExpectedMinConnectionTime": null,
"ActualConnectionTime": null,
"PreviousDirectionIndex": 0,
"NextDirectionIndex": 0
},
"Error": null
}

Open API спецификация

описание метода бронирования