Задача
Закупка на яхту не помещается в обычную корзину интернет-магазина. Одновременно нужно удержать длительность рейса, число и предпочтения участников, меню на каждый день, общие ингредиенты, размеры доступных упаковок, холодильник и сухие отсеки конкретной лодки, отсутствие отдельных товаров в магазине, изменение суммы после замен, разделение оплаты и точное окно доставки в марину.
Без единой системы всё это остаётся ручной работой организатора: собрать пожелания в переписке, пересчитать рецепты и порции, объединить повторяющиеся позиции, подобрать упаковки, сверить объём с возможностями яхты, оформить закупку, распределить итоговый счёт и отдельно координировать курьера. Yachtering сводит эти действия в один управляемый процесс — от параметров путешествия до погрузки продуктов на борт.
Решение
Событие вместо корзины. Организатор начинает со страны обслуживания и языка, указывает количество людей и продолжительность, выбирает яхту и марину. Эти параметры не декоративны: страна определяет доступный каталог и поставщика, продолжительность — число дней меню, количество участников — число персональных слотов, яхта и марина — правила доставки и погрузки. Система формирует ссылку и код доступа, организатор рассылает приглашение, и у каждого участника появляются собственные запись, меню и расчёт. Организатор остаётся участником своего же события, поэтому его блюда и его доля считаются по той же модели, что и у гостей.
Свобода в границах. Участник не может придумать произвольное блюдо — иначе закупка станет непредсказуемой. Вместо этого он выбирает одну из подготовленных альтернатив: рыбное, мясное или растительное основное, заменяет закуску на допустимый вариант, отказывается от ненужной позиции, меняет размер порции, добавляет напитки, учитывает пищевые ограничения и открывает состав и рецепт блюда. Любое такое решение остаётся пересчитываемым в реальные продукты.
Из блюд в упаковки. Блюдо — отдельный тип Magento-продукта, связанный с ингредиентами через product links; рецепт задаёт состав, количество и единицы измерения. После правки меню пересчитываются персональная корзина участника и сводный quote события: один и тот же ингредиент из разных рецептов объединяется, масло и специи не дублируются, а требуемый вес или объём сопоставляется с фактическими розничными упаковками. Для каждой позиции отдельно хранится, какая часть упаковки реально уходит в рецепты, — это позволяет честно разложить стоимость целой пачки между меню, которые её используют.
Вместимость яхты. Заказ проверяется против выбранной лодки и длительности тура: продукты распределяются по холодильнику, сухим шкафам, напиткам и хозяйственным отсекам, контролируется общий объём. Правила погрузки практические — охлаждённое отделяется от сухого, продукты первых дней остаются доступными, общие ингредиенты не разъезжаются по случайным коробкам. Эти данные переходят в инструкции представителю и службе доставки.
Metro и обязательный человек. После подтверждения состав заказа блокируется, и система формирует структурированный закупочный лист для Metro. Дальше включается контроль на месте: представитель сверяет собранную корзину со списком, а при отсутствии позиции подбирает замену, которая сохраняет назначение в рецепте и подходит по хранению и упаковке. Только после проверки в системе фиксируются фактический состав и фактическая сумма — они и становятся основанием для оплаты и бухгалтерских документов. Контур разделён намеренно: расчёт и подготовка заказа автоматизируются, а физическая неопределённость магазина остаётся за человеком.
Деньги по долям. Сводный заказ хранит и общую стоимость, и долю каждого участника. Доля считается по выбранным блюдам, порциям и дополнительным товарам, а стоимость общих ингредиентов и целых упаковок распределяется между использующими их меню. Поддержаны два сценария: каждый оплачивает свою рассчитанную часть либо организатор закрывает заказ целиком и показывает остальным сумму возврата. В checkout — адреса, review заказа, счёт, карточная оплата через Stripe, доставка и сервисные составляющие; у участника есть отдельная страница со своей частью счёта.
Архитектура. Ядро — Magento Open Source 2.4.4: стандартные customer, catalog, quote, order и invoice расширены предметными модулями Event, Menu, Meal / Ingredient / Package, Pricing, Shipping / Checkout / Stripe и Import. Данные выстроены в цепочку «событие → участники → персональные меню → позиции → блюда → ингредиенты и упаковки». У каждого участника свой quote, главный quote события агрегирует все позиции и пересчитывает totals. Замена и удаление блюда идут через AJAX-контроллеры без перезапуска сценария, checkout собран на Vue.js поверх Magento frontend, уведомления рассылают cron-процессы и email sender.
Результат
Организатор перестал быть диспетчером переписки: он задаёт рейс и следит за готовностью меню, остальное считает система. Участник заходит по персональной ссылке, правит только своё меню и видит собственную сумму, оставаясь изолированным от чужих событий. Представитель работает по конкретному списку с понятными правилами замены. Бухгалтерия получает итог заказа, счета и статусы оплаты в готовом виде, а доставка — марину, дату и окно, данные яхты и контакты организатора.
Операционный сценарий оформлен как последовательность состояний — setup, checkout, new/pending, processing, complete, cancelled и closed — с историей статусов, комментариями и флагами уведомлений: видно, на каком этапе событие, кто задерживает решение и какие письма уже ушли. Для разбора спорных ситуаций сохраняется вся цепочка целиком, так что изменение меню, итоговая закупка, финансовая доля и доставка связываются в одну трассируемую последовательность.