Есть свойство заказа типа LOCATION:
Соответственно оно выводится компонентом bitrix:sale.order.ajax для заполнения, но заполняя это поле, после нажатия «Оформить заказ» появляется сообщение об ошибке:
То есть, как будто не видит заполненного значения.
Смотрю DOM, вижу такое:
Таким образом, вводя данные в поле input пользователь вводит в #ORDER_PROP_7_val, а #ORDER_PROP_7 должно как бы само собой заполняться.
Мне показалось, что по какой-то причине не выполняется JS и #ORDER_PROP_7 должен дублировать данные из #ORDER_PROP_7_val, поэтому добавил такой код:
Код |
---|
$(document).on('keyup', '#ORDER_PROP_7_val', function() { var val = $(this).val(); $("#ORDER_PROP_7").val(val); }); |
Технически он работает, но проблему не решает. Компонент всё также не видит заполненного поля.
Дальше я полез в исходники компонента:
Код |
---|
if ($arOrderProps["TYPE"]=="LOCATION" && ($arOrderProps["IS_LOCATION"]=="Y" || $arOrderProps["IS_LOCATION4TAX"]=="Y")) { if ($arOrderProps["IS_LOCATION"]=="Y") $arUserResult["DELIVERY_LOCATION"] = IntVal($curVal); if ($arOrderProps["IS_LOCATION4TAX"]=="Y") $arUserResult["TAX_LOCATION"] = IntVal($curVal); if (IntVal($curVal)<=0) $bErrorField = True; } |
Не разбираясь детально в именах массивов и ключей, видно, что компонент в этом поле ищет число (IntVal) и если не находит — пишет об ошибке.
Так что же делать?
Здравствуйте.
Для формирования заказа в один клик использовал класс Bitrix\Sale\Order.
Возникла проблема с заполнением свойств заказа ФИО, телефон, почта покупателя.
В документации не нашел информации как заполнить именно эти поля, нашел только что их можно заполнить через метод getPropertyCollection().
Методом тыка удалось их заполнить так:
$collection = $order->getPropertyCollection();
$propertyValue = $collection->createItem([
'ID' => 1,
'NAME' => 'NAME',
'TYPE' => 'STRING',
'CODE' => 'PROP_Name',
]);
$propertyValue->setField('VALUE', $name);
$propertyValue = $collection->createItem([
'ID' => 2,
'NAME' => 'PHONE',
'TYPE' => 'STRING',
'CODE' => 'PROP_Phone',
]);
$propertyValue->setField('VALUE', $phone);
$propertyValue = $collection->createItem([
'ID' => 3,
'NAME' => 'EMAIL',
'TYPE' => 'STRING',
'CODE' => 'PROP_Email',
]);
$propertyValue->setField('VALUE', $email);
Заказы создавались корректно пока не обновил Битрикс.
Теперь выдает ошибку mysql
[Bitrix\Main\DB\SqlQueryException]
Mysql query error: (1062) Duplicate entry '1020-1' for key 'IX_SOPV_ORD_PROP_UNI' (400)
INSERT INTO `b_sale_order_props_value`(`ORDER_ID`, `ORDER_PROPS_ID`, `NAME`, `VALUE`, `CODE`, `XML_ID`) VALUES (1020, 1, 'NAME', 'email@email.ru', 'PROP_Name', 'bx_603f258e31ae7')
Заказ создается, но в свойствах заказа информация о покупателе не сохраняется.
Подскажите как правильно передать эти свойства.
Возникает ошибка при оформлении заказа на битрикс (вроде что то связанное с JSON), вот что выходит:
({«order»:{«ERROR»:{«property»:[«\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u043a\u0430\u0437\u0430 \u0022\u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0022 — \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430» ] } } })
Куда копать? Как можно исправить?
- javascript
- json
задан 15 янв 2020 в 8:41
2
-
({"order":{"ERROR":{"property":["Свойство заказа "Местоположение" - ошибка ввода"] } } })
15 янв 2020 в 9:34
-
Спасибо! Буду копать
15 янв 2020 в 10:29
Появилось свободное время и я решил выложить рабочий пример компонента оформления заказа, не просто статью, а проверенный, работающий и функциональный код. За всё время работы с битриксом я довольно много кастомизировал штатный компонент. Написал несколько своих компонентов оформления заказа (первый еще без d7, приблизительно в 2010 году, быстрое оформление во всплывающем окне). Видел варианты реализации от других разработчиков. В общем смею надеяться некоторый опыт в оформлении заказа у меня есть. И весь свой опыт я постарался вложить в новый универсальный компонент.
Вот ссылка на github https://github.com/alorian/bxorder. Это не обрезанный код с существующего проекта. Компонент я писал с нуля, сразу с прицелом на универсальность.
Для начала давайте поговорим о смысле жизни. Зачем это всё вообще надо?
Содержимое статьи
- 1 Зачем нужен компонент?
- 1.1 Что можно улучшить?
- 1.2 Кристально ясное оформление
- 1.3 Стартовое состояние
- 1.4 Работа с пользователями
- 2 Как установить?
- 2.1 Установка с маркетплейс
- 2.2 Установка через composer
- 2.3 Ручная установка
- 2.4 Добавление на страницу
- 3 Как использовать?
- 4 Базис
- 4.1 Файл class.php компонента
- 4.2 Файл result_modifier.php
- 4.3 Шаблон компонента
- 5 Куда отправлять аякс запросы?
- 5.1 Поиск местоположений
- 5.2 Расчет стоимости доставки
- 5.3 Сохранение заказа
- 6 Демонстрационные шаблоны
- 6.1 Дефолтный шаблон
- 6.2 Переключение типа плательщика
- 6.3 Обновление списка доставок
- 7 Что делать если не хватает функционала?
- 8 Дальнейшие планы
TL;DR. Ставим компонент из композера, архивом с гитхаба или из маркетплейс. Пишем собственный шаблон компонента. В шаблоне достаточно сформировать обычную форму с пятью переменными. Компонент отдает в шаблон объект заказа и коллекцию ошибок, превращаем объекты в массив, в файле result_modifier и формируем шаблон как обычно. По необходимости используем готовый аякс для поиска местоположений, расчета доставки или сохранения заказа. Под конкретный проект если не хватает функционала дописываем нужное на событиях или через наследование компонента.
Зачем нужен компонент?
В этом разделе будет немного философии, о том почему сделано именно так, а не иначе и как именно получился итоговый результат, возможности и ограничения Если вам это не особо интересно, то можете сразу перейти к следующему разделу с установкой и просто пользоваться.
Штатный компонент оформления заказа работает хорошо. Как бы кто к нему не относился, в целом сама процедура заказа со стороны покупателя довольно продумана и постоянно совершенствуется. Со стороны разработчика компонент можно более менее модифицировать в каких то рамках. В связи с этим возникает вопрос — а надо ли что-то менять?
Каждый сам должен ответить на этот вопрос. Ответ будет зависеть от конкретного проекта, от бюджета, от сложности доработок, от нужной процедуры оформления. Универсального ответа тут не существует.
На мой взгляд сразу стоит отказаться от варианта с доработкой дефолтного шаблона, от правки html/js. Когда вы захотите это сделать, вы попросту потеряетесь в тысячах строк готового кода. Каждая правка будет вызывать длительную фрустрацию и желание от всего отказаться. Не исключено, что вы доживёте (или уже дожили) до стадии принятия и всё станет хорошо, в этом случае вас остается только поздравить, но большинство останавливается на стадии гнева.
Если штатный шаблон вас в целом устраивает, то вполне можно жить используя разные хаки — что-то придумывать в событиях компонента, писать js скрипты для правок поверх шаблона, жонглировать стилями и т.д.
Однако же если вам нужна простая и лаконичная форма заказа, или более сложная, или даже просто другая, то проще отказаться от штатного шаблона вообще. И возможно от штатного компонента тоже.
Что можно улучшить?
Для понимания масштаба, весь фреймворк symfony в минимальной комплектации это 13к строк в php файлах. Папка с компонентом sale.order.ajax это 11к строк в php файлах и 18,5к строк в js файлах. Эти цифры не для того чтобы кого-то обвинить, совсем нет. По ним вы можете грубо прикинуть количество времени необходимое для изучения темы.
Для начала подумаем о том какой функционал реализует штатный компонент. Почему он такой сложный. И в процессе анализа можно обнаружить, что оформление заказа это довольно простое действие, а значительная часть сложности возникает из-за стороннего никак напрямую не связанного с оформлением функционала. Если бегло пройтись по функционалу, то помимо самого оформления штатный компонент авторизует старых пользователей (да, это прямо в коде компонента), регистрирует новых, работает с профилями покупателей, применяет скидочные купоны. Это всё полито толстым таким слоем галочек из параметров, обработкой событий и набором аякс методов. Тщательно размешиваем и получаем идеальный хаос 🙂
Повторять весь функционал старого компонента в новом и надеяться, что в этот раз получится наоборот, нечто кристально ясное и прекрасное — это тупиковый путь. Нужно пробовать кардинально другой подход.
Чутка подумаем над общей архитектурой. Для получения кристальной ясности мы должны разбить код на слабосвязанные блоки. Каждый блок должен осуществлять какую-то отдельную функцию, делать ее хорошо и при этом быть такого размера, чтобы любой разработчик мог целиком поместить его в голову без долгих многодневных медитаций.
Выделим три главных блока — работа с пользователями (авторизация и регистрация), работа с профилями пользователей (стартовое состояние страницы заказа) и собственно суть всей процедуры — блок оформления заказа.
Для авторизации и регистрации у нас уже есть готовые компоненты, нужно только разобраться как их правильно использовать. Работу с профилями пользователей пока вынесем за скобки. Сначала сосредоточимся на главной части, подумаем о том что мы хотим видеть в процедуре оформления заказа.
Кристально ясное оформление
Битрикс развивается и довольно много удобных вещей уже реализовано. ООП архитектура интернет магазина на мой взгляд получилась крайне удачной. Люди привыкли работать с объектами в реальном мире, поэтому мне кажется довольно просто понять что такое объект заказа и держать его в голове. Яблоки на прилавке — товар, яблоки в пакете по дороге домой — сохраненный объект заказа. Можно оптимизировать внутренности объекта заказа, делать его более понятным и функциональным, однако же в плане концептов тут уже нечего улучшать. У тебя есть условный пакет яблок и ты можешь делать с ним что захочешь.
А что люди реально хотят делать с объектом заказа? Вариантов миллион. Яблоко можно просто съесть, сделать компот, сделать повидло, фруктовый салат, можно достать семена и посадить яблоню. И если мы в самом компоненте будем формировать массив $arResult, который пригодится вообще во всех возможных случаях, то мы опять придем к тому, что компонент разрастется и перестанет быть доступным для понимания. Это список новостей всегда будет выглядеть примерно одинаково, а в процедуре оформления заказа фантазия может разгуляться. Отсюда первый вывод — для универсальности мы должны полностью отказаться от массива $arResult в компоненте. Компонент на выходе должен отдавать только объект заказа.
Но ведь $arResult реально удобен и в шаблоне компонента гораздо понятнее выглядит строка «echo $arResult[‘SUM’]», чем вызов «SaleFormatCurrency($order->getPrice(), $order->getCurrency())». Ничего страшного во втором варианте нет, однако же первый выглядит проще и лаконичнее, а мы боремся за кристальную ясность. В структуре компонента битрикс есть идеальное место для формирования массива $arResult — это файл result_modifier.php. Отсюда второй вывод, чтобы упростить понимание процедуры заказа мы должны формировать массив $arResult до старта шаблона компонента, а в шаблоне уже пользоваться заранее подготовленным массивом.
Что еще не учтено? Обработка ошибок. В процессе заполнения объекта заказа компонент может сгенерировать какие либо ошибки, которые мы пока что никак не передаем в шаблон. В объекте заказа они не хранятся, от $arResult мы отказались. Поэтому все же придется чуть усложнить концепт, компонент оформления заказа должен возвращать не только объект заказа, но и коллекцию ошибок. В битриксе для коллекции ошибок опять таки есть готовая реализация, это класс «Bitrix\Main\ErrorCollection». Сами ошибки внутри хранятся тоже в виде объектов.
Расставим всё по полкам в последний раз. В коде компонента мы формируем два публичных объекта — объект заказа и коллекцию ошибок. Далее из этих двух объектов в result_modifier мы собираем массив $arResult. И уже в шаблоне формируем с помощью $arResult итоговый html+js+css.
Стартовое состояние
Важной частью штатного sale.order.ajax является работа с профилями. Что такое профиль покупателя, если смотреть в самую суть? Это только стартовое состояние формы заказа. Если мы переключаем профиль, то стартовое состояние формы (заполненные значения в полях) меняется. При этом любые исправления стартового состояния имеют безусловный приоритет, если пользователь поменял текст в каком то поле, то значение из профиля мы должны игнорировать.
Таким образом что должен делать блок работы с профилями? Где-то выше компонента оформления заказа он должен сформировать массив со стартовыми полями заказа. И далее передать этот массив в компонент.
Как мы можем красиво передать данные в компонент? Для этого опять таки есть хороший штатный вариант — параметры компонента. Именно поэтому при отсутствии данных в http post запросе, объект заказа наполняется данными из параметров компонента.
Многие отказываются от штатной системы профилей и хранят данные так как им удобно (например в hl-блоках), данные с реквизитами компании отдельная сущность, данные о контактных лицах отдельно, адреса отдельно и т.д.. В текущей реализации опенсорсного компонента абсолютно неважно как вам нравится хранить данные, просто формируете массив и кидаете его в параметры компонента.
Работа с пользователями
Я вижу всего три сценария работы с пользователями. Первый, когда пользователи нам вообще не важны, работаем по каждому конкретному заказу отдельно, возможно даже без регистрации пользователя вообще. Второй, когда нам пользователи очень важны и мы даже не показываем форму заказа без авторизации. И третий промежуточный, когда мы регистрируем нового пользователя в момент сохранения заказа.
На текущий момент опенсорный компонент оформления заказа вообще никак не взаимодействует с пользователями. Если в момент сохранения заказа пользователь не авторизован, то сам битрикс (не компонент) вернет ошибку «Не заполнено обязательное поле «USER_ID»». Таким образом сразу после установки компонент может работать только по второму сценарию, когда пользователи нам очень важны.
Что же касается первого и третьего сценария работы с пользователями, то вам придется доработать нужную логику самостоятельно. Там опять таки слишком много возможных вариантов. О том как это сделать в одном из разделов статьи ниже. Ничего волшебного там нет, для реализации первого сценария хватит пары строк в обработчике OnSaleOrderBeforeSaved, для реализации третьего сценария можно уложиться в двадцать.
Как установить?
Установка доступна с помощью композера, через маркетплейс битрикс и просто вручную, архивом.
Установка с маркетплейс
Чтобы воспользоваться компонентом без участия композера, перейдите по ссылке на маркетплейс битрикса — http://marketplace.1c-bitrix.ru/solutions/opensource.order/. И установите решение как обычно (если там пусто, то возможно я его еще не подготовил, либо оно еще на модерации).
Установка через composer
Для начала пропишите в своем composer.json путь до папки bitrix. Обратите внимание на блок extra:
{
"name": "your/project",
"authors": [
{
"name": "Alexander Shubin",
"email": "alorian@yandex.ru"
}
],
"require": {},
"extra": {
"bitrix-dir": "./"
}
}
Путь до папки bitrix нужно прописывать относительно файла composer.json. Например если файл composer.json лежит в /local/libs,
то нужно прописать «bitrix-dir»: «../../bitrix». По дефолту установщик считает, что файл composer.json лежит в document_root.
Если не указать корректный bitrix-dir, то будет создана папка bitrix/modules/opensource.order/ рядом с composer.json.
После того как прописали правильный bitrix-dir выполните:
$ composer require alorian/bxorder
После выполнения команды откройте список модулей маркетплейс в админке /bitrix/admin/partner_modules.php?lang=ru, если
bitrix-dir был указан корректно, то вы увидите строку с модулем opensource.order. Нажмите «Установить» в выпадающем меню.
Ручная установка
Скачайте архив https://github.com/alorian/bxorder/archive/master.zip и самостоятельно распакуйте его содержимое в папку модулей битрикса — /bitrix/modules, либо /local/modules.
В папке модулей у вас должна быть папка opensource.order, а не bxorder-master, папку bxorder-master которая лежит
в архиве необходимо переименовать. Таким образом полный путь до файла include.php у вас должен быть /bitrix/modules/opensource.order/include.php, либо /local/modules/opensource.order/include.php
После распаковки архива откройте список модулей маркетплейс в админке /bitrix/admin/partner_modules.php?lang=ru,
найдите строку с модулем opensource.order и нажмите «Установить» в выпадающем меню
Добавление на страницу
Вне зависимости от того как вы установили модуль, через композер или через маркетплейс, в любом случае открываем какую-либо страницу в визуальном редакторе и размещаем компонент на странице:
После этого, даже без каких либо дополнительных настроек вы увидите дефолтный демонстрационный шаблон:
В зависимости от шаблона сайта визуально страница может выглядеть по другому, но основные блоки будут такими же как на скриншоте.
Как использовать?
Что вам нужно сделать как программисту для интеграции верстки? В самом простом случае вам всего лишь нужно сформировать форму (html тэг <form>) в шаблоне компонента, которая при отправке передаст на сервер пять переменных:
- person_type_id. Переменная которая содержит тип плательщика.
- properties[]. Массив переменных со свойствами заказа. Например, если у свойства символьный код — FIO, то атрибут name у инпута ставьте properties[FIO]. Если переменная множественная то ставьте name=properties[FIO][]
- delivery_id. В самом простом случае это просто input типа radio, у которого атрибут name=delivery_id
- pay_system_id. Так же как и с доставкой, просто radio инпут, только атрибут name=pay_system_id
- save. Если переменная save=y, то компонент сохранит заказ. Во всех остальных случаях компонент просто обновит данные в объекте заказа и отдаст шаблон.
Да, всё настолько просто. Формируете форму с этими пятью переменными и вы великолепны. Это далеко не всё что можно сделать с помощью опенсорсного компонента. Но даже в самых сложных шаблонах суть останется прежней. Оформление заказа это не магия, просто обычная форма в браузере, просто чуть больше полей чем в обратной связи.
Базис
У компонента есть три отдельных части, три кита на которых всё держится. Каждый из них отвечает за свою область и строго специализирован. Постарайтесь понять цель каждой отдельной части.
Рассматривайте каждую из частей как черный ящик. С одной стороны запихиваем в ящик какие то данные, трясем, и на выходе с другой стороны получаем нечто новое. У ящика есть вход и выход.
Если вы поймете этот базис, этот ключевой концепт, то сможете построить любую процедуру оформления.
Файл class.php компонента
Именно с этого файла начинается работа всего компонента. Основная цель этого файла — создать объект заказа и передать его дальше.
Массив $arResult вообще не используется. Компонент в результате своей работы формирует всего две публичные переменные — переменную $this->order с объектом заказа и переменную $this->errorCollection с ошибками.
Для построения объекта заказа могут быть использованы два источника — параметры компонента и переменные запроса. При первом открытии никаких переменных запроса у нас разумеется нет, в этом случае все пять переменных будут получены из параметров компонента. Но данные из запроса приоритетнее. То есть при наличии данных в запросе, параметры компонента будут проигнорированы.
Итого. На вход компоненту мы подаем массив параметров компонента и массив данных из http запроса. На выходе из компонента мы получаем объект заказа и коллекцию ошибок.
Файл result_modifier.php
Основная цель этого файла — сформировать массив $arResult и передать этот массив в шаблон.
На выходе из компонента мы получили объект заказа. В принципе можно сразу в шаблоне компонента пользоваться методами этого объекта, без формирования $arResult вообще. Однако же с предварительно сформированным $arResult, в шаблоне код получается более чистым и понятным. Помимо чистоты кода массив $arResult вам понадобится для использования во vue.js или react.js, так как для передачи на фронт переменные в любом случае придется доставать из объектов.
На вход в result_modifier.php мы получаем объект заказа и коллекцию ошибок, на выходе мы отдаем $arResult с данными для шаблона.
Шаблон компонента
Как и в любом другом шаблоне битрикса мы должны сформировать html код который будет отображаться в браузере. Плюс по необходимости в шаблоне мы можем подключить дополнительные скрипты и стили.
На вход шаблона мы получаем массив $arResult, на выходе шаблон отдает готовый html код, плюс скрипты и стили если это необходимо. Если вы используете webpack+vue/react, то в шаблоне просто передаем массив $arResult в браузер через глобальный window.
Куда отправлять аякс запросы?
Ничто не мешает вам отправить данные в какой то свой контроллер и полностью самостоятельно формировать ответ сервера, однако же возможно вам хватит готовых функций.
Аякс работает с помощью нового механизма аякс, о котором я писал в статье по ссылке. В простом случае никакие аякс запросы вам не понадобятся. Достаточно просто сформировать html форму без скриптов вообще и отправить ее по кнопке submit на эту же страницу. Однако для чуть более сложных сценариев вы можете воспользоваться следующими готовыми методами:
Поиск местоположений
Файл ajax.php в папке компонента. Метод searchLocationAction в классе OpenSourceOrderAjaxController. Сам поиск осуществляется с помощью штатного метода \Bitrix\Sale\Location\Search\Finder::find. Далее по каждому из найденных местоположений собирается полная информация, в том числе путь от корня — страна, регион, область, и т.д. Можно получить эту же информацию в обратном порядке — местоположение, область, регион, страна.
На вход метод принимает четыре параметра:
1. Поисковая строка string $q, любая фраза по которой осуществляется поиск. Например при вводе «санкт» битрикс с большой долей вероятности найдет «Санкт-Петербург».
2. Количество поисковых результатов, int $limit = 5. Сколько найденных местоположений вам придет в ответе. В коде стоит проверка — не меньше одного местоположения и не больше пятидесяти.
3. Тип местоположений, string $typeCode. Если вам нужны только города, то передайте аргумент $typeCode = ‘CITY’. По умолчанию поиск осуществляется вообще по всем типам местоположений.
4. Исключение каких то частей и найденного названия, array $excludeParts = []. Если в названии найденного местоположения вам не нужна страна и округ, то просто передайте в этот аргумент значение [COUNTRY, COUNTRY_DISTRICT] и в ответе вам придет название местоположения начиная с региона.
Всего в битриксе есть семь дефолтных типов местоположений. Любое местоположения которое хранится штатно в таблице местоположений будет принадлежать одному из семи типов — COUNTRY, COUNTRY_DISTRICT, REGION, SUBREGION, CITY, VILLAGE, STREET.
5. Порядок формирования имени, string $sortOrder = ‘desc’. Как я говорил выше, найденное местоположение может быть отдано в формате страна, округ, регион и т.д., а может быть наоборот в формате регион, округ, страна. В этом параметре вы можете указать нужный порядок.
Возвращает массив найденных местоположений:
Array
(
[0] => Array
(
[name] => Москва
[code] => 0000073738
[type] => CITY
[type_name] => Город
[label] => Москва, Центр, Россия
[parts] => Array
(
[CITY] => Array
(
[name] => Москва
[code] => 0000073738
[type] => CITY
[type_name] => Город
)
[COUNTRY_DISTRICT] => Array
(
[name] => Центр
[code] => 0000028024
[type] => COUNTRY_DISTRICT
[type_name] => Округ
)
[COUNTRY] => Array
(
[name] => Россия
[code] => 0000028023
[type] => COUNTRY
[type_name] => Страна
)
)
)
[...]
)
Расчет стоимости доставки
Файл ajax.php в папке компонента. Метод calculateDeliveriesAction в классе OpenSourceOrderAjaxController. В методе как обычно создается объект заказа и отгрузка. По отгрузке выбираются все доступные доставки и рассчитывается стоимость этих доставок.
На вход принимает три параметра:
1. Тип плательщика, int $person_type_id.
2. Массив свойств, array $properties. В массиве должно быть как минимум одно свойство — свойство с местоположением. Иначе доставки ничего не смогут рассчитать. Лучше всего передавать вообще все свойства из формы заказа.
3. Массив ID доставок, array $delivery_ids. Может быть пустым, но если задан, то будут рассчитаны доставки только с указанными ID. Доставки в любом случае должны быть доступны для заказа.
Возвращает массив с рассчитанной стоимостью доставок:
Array
(
[2] => Array
(
[id] => 2
[success] => 1
[name] => Доставка курьером
[logo_path] => /upload/sale/delivery/logotip/789/78984a7a84ff245422e5abd911c1972a.png
[period] =>
[base_price] => 500
[base_price_display] => 500 руб.
[price] => 350
[price_display] => 350 руб.
[discount] => 150
[discount_display] => 150 руб.
[errors] => Array
(
)
)
[...]
)
Сохранение заказа
Файл ajax.php в папке компонента. Метод saveOrderAction в классе OpenSourceOrderAjaxController. По сути вызываются те же самые методы основного компонента, что и при отправке формы на страницу. Полный аналог executeComponent, за исключением вывода шаблона. Результат сохранения заказа, либо ошибки отдаются в виде чистых данных.
Демонстрационные шаблоны
На текущий момент все готовые шаблоны это просто демонстрация возможностей для программистов. Сам компонент полностью готов и хорошо спроектирован, однако готовых шаблонов на текущий момент нет. Возможно в будущем они появятся.
Дефолтный шаблон
Скрин с дефолтной формой заказа я приводил в начале статьи. Там есть пять основных блоков:
1. Таблица со списком свойств. В шаблоне реализовано отображение свойств типа строка, чекбокс Да/Нет, выбор из списка значений, заполнение даты и поиск местоположений.
При наличии ошибок по какому либо свойству, например если свойство не заполнено, или заполнено неверно, текст ошибки отобразится отдельно прямо в строке со свойством.
2. Выбор службы доставки. Стоимость доставок рассчитывается при открытии страницы, при смене местоположения стоимость не меняется. При наличии ошибок связанных с доставкой, текст ошибок отобразится прям в этом блоке.
3. Выбор платежной системы. Блок из обычных радио инпутов плюс вывод списка ошибок связанных с оплатой.
4. Таблица с товарами в корзине. Текстовая информация, можно посмотреть как именно правильно доставать различные цифры из корзины, как получить значение скидки, как работать со свойствами товаров корзине и отображать единицы измерения.
5. Итоговая информация по заказу. Опять же просто информационный текст, в этом блоке ничего не заполняется. Я показал как можно отобразить девять самых популярных цифр по заказу. Выводить их или нет в своем шаблоне — решать вам.
Переключение типа плательщика
По сравнению с дефолтным шаблоном здесь добавилось не так и много. В result_modifier немного изменено получение списка свойств, так как нужны свойства не только по текущему плательщику, но и по всем остальным.
В самом шаблоне формируются отдельные таблицы свойств для каждого типа плательщика. Добавлен переключатель типа плательщика. При переключении скрываются все таблицы свойств, кроме таблицы выбранного плательщика. Всем элементам ввода свойств при переключении добавляется атрибут disabled, таким образом при отправке формы они будут проигнорированы, реально отправятся только инпуты из таблицы свойств выбранного плательщика.
Обновление списка доставок
Это тот же самый дефолтный шаблон, но в файле script.js шаблона добавлен обработчик на изменение свойств типа location. При изменении свойства с типом location отправляется аякс запрос на расчет стоимости доставки. После получения результата расчета текущий список доставок очищается и строится заново по данным пришедшим из аякс.
То есть по сути отличается только файл script.js и немного отличается вывод списка доставок, чтобы можно было из скрипта удобнее их очищать.
Что делать если не хватает функционала?
Если вы считаете, что не хватает какого-то общего функционала, то вы можете написать его самостоятельно и отправить pull request. Кратко для тех кто не сталкивался с опенсорсом. Вы делаете форк репозитория, в своем форке добавляете функционал и отправляете pull request из форка в оригинал. Я увижу что именно вы добавили, если код хорошо написан и будет полезен многим, а не только вам, то этот pull request будет влит в основную ветку.
Если вы хотите написать какой то функционал под конкретный проект, то у вас есть две пути — события и наследование компонента.
Для начала про события. Допустим вы хотите отображать форму вообще всем пользователям даже без авторизации, и регистрировать пользователя в момент сохранения заказа. Можете использовать обработчик перед сохранением заказа OnSaleOrderBeforeSaved. В этот обработчик вы получаете объект заказа. Если это новый заказ ($order->isNew()), то регистрируете пользователя как вам хочется, а потом подставляете ID только что созданного пользователя в заказ через $order->setFieldNoDemand(‘USER_ID’, $userId).
В OnSaleOrderBeforeSaved можно добавить любые проверки по данным заказа и возвращать ошибки. Эти ошибки будут добавлены в общую коллекцию ошибок и переданы в шаблон.
Второй путь — наследование компонента. Вы можете прочитать об этом в документации. Допустим вы считаете, что проверка свойств слишком простая. Наследуете компонент и перекрываете метод validateProperties() в классе компонента. У вас будет новый класс компонента всего с одним методом:
<?php
use Bitrix\Main\Result;
CBitrixComponent::includeComponentClass('opensource:order');
class InheritedOpenSourceOrderComponent extends OpenSourceOrderComponent
{
/**
* @return Result
*
* @throws Exception
*/
public function validateProperties()
{
$parentResult = parent::validateProperties();
$result = new Result();
//добавляем свою логику
if (!$parentResult->isSuccess()) {
$result->addErrors($parentResult->getErrors());
}
return $result;
}
}
Аналогичным образом можно переписать любой метод компонента. Можно даже не вызывать родительский метод, если ваша логика отличается от дефолтной. Не обязательно только переписывать какие то методы, можно добавлять новые.
Дальнейшие планы
Скорее всего будет пример шаблона на vue. Я пробовал сделать пример на bx.vue, но без транспиляции кода и импорта я чувствую себя очень не комфортно. Многие готовые компоненты vue не получается добавить подключением из CDN. Поэтому пока что отложил эту задачу. Посмотрим как это лучше всего реализовать. Планирую написать отдельную статью по процедуре заказа на vue.
Сам компонент будет развиваться. Есть некоторые вещи которые я хочу улучшить. Кардинально ничего не поменяется, вы всё так же можете рассчитывать на объект заказа и коллекцию ошибок в шаблоне.
А так в целом, жду пул реквесты и просто текстовые предложения по улучшению функционала в комментариях к этой статье или в issues на гитхабе https://github.com/alorian/bxorder/.
2 / 2 / 0 Регистрация: 05.06.2012 Сообщений: 71 |
|
1 |
|
Занесение значения в свойство заказа при оформлении покупок03.02.2014, 13:21. Показов 17205. Ответов 14
Есть некоторое свойство заказа, назовем его «Закупочная цена». Известен его ID (40), оно применяется для всех типов плательщиков, оно служебное, активное и имеет мнемонический код. Немного модифицировав стандартный битриксовский компонент оформления заказа (sale.order.ajax), я получил закупочную цену всего заказа. Далее мне нужно при оформлении заказа занести это значение в наше свойство заказа «Закупочная цена». Чтобы потом в профиле заказа можно было узнать закупочную цену. В документации битрикса нашел только SaleOrderUserPropsValue::Update, но так и не понял как его применить к моей задаче. Если не сложно, может кто на моем примере показать как при оформлении заказа мне заносить значение в это свойство заказа.
0 |
284 / 283 / 73 Регистрация: 06.05.2013 Сообщений: 1,613 |
|
04.02.2014, 13:15 |
2 |
Сделайте его неслужебным, в шаблоне просто скройте его, чтоб пользователи его не видели и заполняйте его в шаблоне sale.order.ajax, тогда при добавлении заказа это свойство будет записываться
0 |
2 / 2 / 0 Регистрация: 05.06.2012 Сообщений: 71 |
|
04.02.2014, 15:03 [ТС] |
3 |
Сделайте его неслужебным, в шаблоне просто скройте его, чтоб пользователи его не видели и заполняйте его в шаблоне sale.order.ajax, тогда при добавлении заказа это свойство будет записываться А если все делать «правильно», то как мне быть в этом случае?
0 |
284 / 283 / 73 Регистрация: 06.05.2013 Сообщений: 1,613 |
|
04.02.2014, 15:40 |
4 |
Faire, Не могу сказать, хотя в общем это не самый плохой костыль, по сути может так и надо)
0 |
Faire 2 / 2 / 0 Регистрация: 05.06.2012 Сообщений: 71 |
||||
04.02.2014, 17:22 [ТС] |
5 |
|||
Хм, сделал как Вы советовали (в template.php):
Но по какой то причине свойство все равно не заполняется, хотя на странице с оформлением заказа его значение правильное (через print_r[$arProperties[«VALUE»] показывает верное значение). Может что то не так с настройками свойства (скрин http://d.pr/i/QmFy)?
0 |
284 / 283 / 73 Регистрация: 06.05.2013 Сообщений: 1,613 |
|
04.02.2014, 17:27 |
6 |
А у Вас там как вообще страница рисуется? Там поля для ввода данных есть? Просто наверное надо сделать именно скрытое поле, при оформлении заказа происходит отправка формы со всеми полями, если там будет Ваше поле, то оно запишется.
1 |
tgarl 444 / 411 / 113 Регистрация: 15.02.2012 Сообщений: 1,816 |
||||
05.02.2014, 16:56 |
7 |
|||
как-то очень сложно вы пытаетесь реализовать — вот пример мне нужно было отправить дату вылета при покупке билета
соответсвенно в корзину попадает элемент каталога билет у которого свойство будет дата вылета. правда добавление в корзну я делал через свой аякс(не стандартный). но если хотите через стандартный каталожный аякс то в $arParams есть значение в которое передается свойство которое будет добавлено в корзину. мне нужно было не у всех товаров а у конкретных с определенными условиями, поэтому я не пользовался стандартным — он так не позволит.
1 |
0 / 0 / 0 Регистрация: 15.01.2016 Сообщений: 4 |
|
15.01.2016, 11:01 |
8 |
tgarl, расскажите пожалуйста подробнее как вы это сделали? В общем — если кратко, то — как вы сохраняли свойство Дата вылета в корзину, а потом в заказ??
0 |
444 / 411 / 113 Регистрация: 15.02.2012 Сообщений: 1,816 |
|
15.01.2016, 12:23 |
9 |
функция Add2BasketByProductID имеет 3(сейчас уже 4, но можно передавать и 3) входящих параметра: id элемента, количество и свойства
1 |
0 / 0 / 0 Регистрация: 15.01.2016 Сообщений: 4 |
|
15.01.2016, 13:26 |
10 |
tgarl, как вы создали свойство дата? далее в этой функции ф получаю необходимые значения со страницы как вы это делаете? Я не сильна в программировании, поэтому прошу описать процесс подробнее…уже долго мучаюсь, не знаю как решить проблему с передачей свойств в корзину.
0 |
tgarl 444 / 411 / 113 Регистрация: 15.02.2012 Сообщений: 1,816 |
||||
15.01.2016, 13:53 |
11 |
|||
там был отдельный инфоблок с датами вылета рейсов. в шаблоне компонента сделал input c календариком в котором проставлены все даты из того инфоблока.
1 |
0 / 0 / 0 Регистрация: 15.01.2016 Сообщений: 4 |
|
15.01.2016, 13:59 |
12 |
tgarl, вот оно что… у меня совсем это не получается не понятно как сохранять свойство в корзине… Добавлено через 5 минут
data=$(«#data_vileta»).val(); Как Вы эти значения сохраняли в корзине и соответственно в заказ?
0 |
tgarl 444 / 411 / 113 Регистрация: 15.02.2012 Сообщений: 1,816 |
||||||||
15.01.2016, 15:11 |
13 |
|||||||
я могу только в общих чертах говорить, проектом тем уже не занимаюсь достаточное время. сайт был по продаже туров и билетов к ним. там были отдельно все элементы: туры, ценовые предложения по турам(от коэфицентов заезда в отель зависили — отдельный модуль генерации делался и генерировал 100k+ вариантов), отели, билеты, даты вылета(генерировались тоже). так что как там все было завязано точно не скажу. наворотов было ого
в обработчике
в обработчике код закидывает в корзину товар с указанием его количества и свойства
1 |
0 / 0 / 0 Регистрация: 15.01.2016 Сообщений: 4 |
|
15.01.2016, 17:19 |
14 |
tgarl, скажите, а как вы настраивали в инфоблоке это свойство дата? какой тип имеет это свойство в инфоблоке и множественное оно или нет. если оно не множественное и не список то каком образом у оно сохраняется? потому что у меня битрикс отказывается сохранять не множественное и не список Добавлено через 1 час 57 минут
0 |
444 / 411 / 113 Регистрация: 15.02.2012 Сообщений: 1,816 |
|
15.01.2016, 18:41 |
15 |
строка, не множественное, все даты отдельными элементами битрикс отказывается сохранять не множественное и не список что значит битрикс отказывается сохранять? проверьте на ошибки систему /bitrix/admin/site_checker.php?lang=ru тут тогда будет ошибка если что-то не так
0 |