Задача
Каждая станция приходит со своим договором, и почти всё в продукте от него зависит: какой каталог ей видно, какие категории и страницы доступны, сколько credits начисляется сразу и сколько повторяется каждый период, какой membership-уровень действует, какие операции требуют согласования iMAR. Без единого контура эти условия пришлось бы переносить в рабочие системы вручную — отдельно заводить доступ станции и её сотрудников, сверять лимиты, собирать подборки для победителей конкурсов, резервировать credits, согласовывать пакеты и передавать данные между CRM, бухгалтерией и системами бронирования.
Решение
Договор как конфигурация. Документ загружается в защищённый раздел и связывается с аккаунтом станции. AI-агент извлекает значимые условия и нормализует их в параметры платформы: статус договора и период действия, первоначальное и регулярное начисление credits, день и правила пополнения, membership-уровень со сроком и преимуществами, доступные категории, продукты и CMS-разделы, роли и ограничения аккаунта, условия approvals. Исходный документ хранится рядом с созданной по нему конфигурацией — сотрудник может проверить, как пункт договора превратился в настройку, а не принимать результат на веру.
Договорный модуль. Состояния — pending, active, paused, cancelled и ended. Плановый процесс сам активирует наступившие договоры и выполняет предусмотренное регулярное пополнение wallet. Корректировки, паузы, возобновления и начисления попадают в историю, поэтому состояние credits восстанавливается по операциям, а не только по текущему остатку. Membership проверяется вместе с договором и правами пользователя при открытии каталога и оформлении пакета.
У каждой станции свой каталог. Права применяются к товарам, категориям и контентным страницам, поэтому две станции с разными договорами видят разную витрину. Карточка experience содержит фотогалерею и обзор пакета, регион, состав включённых услуг, itinerary, дополнительные опции, период доступности и крайний срок заявки, credit value и eligibility конкретной станции, отметку о необходимости ручного подтверждения iMAR. Для нестандартного запроса есть custom experience: станция описывает нужный формат, дальше его подхватывает операционная команда.
Guest lists — самый неочевидный узел. Победителю конкурса обычно не назначают поездку заранее: ему дают контролируемый выбор. Сотрудник станции собирает список из каталога, указывает данные получателя, задаёт допустимое число выбранных experiences и максимальный credit allocation и отправляет защищённую token-ссылку. В момент отправки платформа резервирует максимально возможный объём credits — иначе гость мог бы выбрать пакет, который станция уже не в состоянии оплатить. Получатель открывает анонимную ссылку, видит только разрешённую подборку и выбирает в заданных границах; система автоматически создаёт заказ, а неиспользованная часть резерва возвращается в кошелёк станции. Списки живут в состояниях waiting, sent, redeemed и cancelled, приглашение можно отправить повторно или отменить.
Approvals и бронирование. Часть пакетов требует ручного согласования. Credits при оформлении сначала резервируются, сотрудник iMAR проверяет доступность и может подтвердить заявку полностью, подтвердить допустимую часть или отклонить её; неиспользованный или отклонённый резерв освобождается автоматически. Для подтверждённого пакета формируются booking-запись, связанный заказ и redeem code, получателя можно назначить сразу или позже, после чего ему уходит уведомление. Подтверждённые данные передаются в booking-системы, история взаимодействий и статусы — в CRM, финансовые документы и проводки — в бухгалтерский контур.
Wallet как ledger. Кошелёк станции показывает общую, доступную, использованную и зарезервированную части allocation, а каждая операция имеет тип и основание: договорное начисление, выделение credits подчинённому пользователю, резерв под guest list или бронирование, списание после подтверждения, возврат при отмене или частичном approval, ручная корректировка с причиной. Такой учёт отличает реально потраченные credits от временно зарезервированных и объясняет любое изменение баланса конкретным договором, пользователем, списком или заказом.
Архитектура. Витрина — PWA на Vue Storefront 1.12.3 и Vue.js 2 с SSR, service worker, установкой на устройство и push-уведомлениями. Она обращается к API на Node.js и Express, который связывает storefront с Magento 2.4.4, Elasticsearch и дополнительными модулями; Magento остаётся ядром commerce-логики и административным back office, а данные каталога синхронизируются в Elasticsearch отдельным процессом. Рядом работают Redis и Kue для очередей и фоновых задач и Varnish для кэширования; периодические операции ведут договорные начисления, смену состояний и синхронизацию данных.
Изоляция и история. Каталог, заказы, кошелёк и документы фильтруются по организации, customer group, роли и индивидуальным разрешениям, а guest token открывает только конкретную подборку и не даёт доступа к аккаунту станции. История фиксирует загрузку и применение договора, изменения статуса, начисления, резервы, списания, возвраты, отправку списка, выбор получателя, решения iMAR и последующее redemption — финансовые и операционные исключения разбираются без ручного сведения данных из разных систем.
Результат
Бартерный договор перестал быть документом, который кто-то держит в голове, и стал исполняемой конфигурацией продукта. Администратор станции видит в кабинете договор, membership, кошелёк, активность сотрудников и бронирования, распределяет credits между подчинёнными пользователями и выгружает месячный отчёт по credits вместе с отчётами по продажам, bestsellers и брошенным корзинам. Сотрудник станции собирает подборку победителю за несколько минут и не рискует превысить бюджет: лимит проверяется резервом, а не памятью. Получатель выбирает поездку по одной защищённой ссылке, ничего не зная о внутренних лимитах станции. iMAR обрабатывает заявки в единой очереди approvals, где рядом с запросом видны условия договора, зарезервированные credits и доступность пакета во внешней booking-системе.