При разработке мы старались максимально обеспечить совместимость нового магазина со старыми версиями, но обеспечить 100% совместимость при такой масштабной переработке невозможно. Ниже в статье я опишу места, на которые надо обратить особое внимание при переходе на новый магазин. Если у вас есть вопросы, предложения, пожелания или требуется консультация - обращайтесь к нам через службу техподдержки.
Существенно изменилась структура таблиц в базе данных.
Мы всегда говорили, что прямой доступ к таблицам - это не правильный вариант работы с обновляемым продуктом. Но если вы все же по тем или иным причинам напрямую запрашиваете базу данных, то велика вероятность, что вам придется внести изменения в свои алгоритмы. Правильный доступ к данным должен производиться через АПИ модуля.
Заказ, оплаты, доставки – связь «один-ко-многим».
Раньше в магазине была одна сущность - заказ, который представлял собой одну запись в таблице заказов. В этой таблице было поле, в котором хранился код платежной системы, поле со статусом оплаты и т.д. В новом магазине у каждого заказа может быть неограниченное число (частичных) оплат/счетов, а так же неограниченное число отгрузок. У каждой оплаты свой статус оплаченности, своя дата оплаты и т.п.
Другими словами появляется связь «один-ко-многим» между заказом и оплатами/отгрузками. Соответственно если выбрать из базы пару значений "заказ - оплата", то либо оплата там будет какая-то одна из имеющихся (не все), либо один и тот же заказ будет в нескольких парах (по числу оплат).
Мы постарались обеспечить максимально возможную совместимость. Если у вас не используется разделение на несколько оплат для одного заказа, то через старый АПИ можно выбрать сразу и заказ и его одну оплату. Но как только у вас появится разделение - результат выборки может оказаться не такой, на который вы рассчитываете.
Все, что сказано про оплаты, верно и для отгрузок.
Рекомендовать тут можно только либо постепенно переходить на новый АПИ в ваших решениях (рекомендуется), либо всегда для одного заказа иметь только одну оплату и только одну отгрузку.
Оплата с внутреннего счета.
Раньше при оплате с внутреннего счета просто в таблице заказа проставлялась соответствующая сумма. В новом магазине внутренний счет - такая же платежная система, как и все остальные. Соответственно оплата с внутреннего счета - такая же запись (частичной) оплаты, как и для любой другой платежной системы. Таким образом облегчается отслеживание оплат, а кроме того на внутренний счет можно наложить условия и ограничения (как на любую другую платежную систему).
Полностью переработан жизненный цикл заказа.
Так как изменилась структура и работа заказа, то соответственно изменился и жизненный цикл заказа. Мы восстановили основные события того жизненного цикла, который был раньше. Они включаются и выключаются в настройках модуля. Но места вызова старых событий в новом магазине не соответствуют старым местам вызова (потому что старых мест уже нет). В большинстве случаев это не должно повлиять на успешное выполнение вашего обработчика события, но лучше после перехода на новый магазин перепроверить, что все работает правильно. Еще лучше, конечно, перейти на новые события.
Новый АПИ автоматически всегда поддерживает арифметическую целостность заказа.
Раньше программно можно было записать в любые поля заказа любые значения, и это успешно сохранялось, даже если логически данные не соответствовали друг другу. Например, при использовании старого АПИ можно было создать заказ стоимостью 1 руб., в котором было товаров на 500 руб. В новом магазине стоимость такого заказа будет 500 руб. (плюс возможно стоимость доставки).
Меняются реальные ID платежных систем и служб доставок.
В связи с изменением структуры и работы платежных систем и служб доставок, меняются их реальные ID. У служб доставок теперь нет архитектурного разделения на настраиваемые и автоматизированные, соответственно нет и строковых идентификаторов, они теперь числовые. Все внутренние данные и сущности сами переходят на новые ID при конвертации. Если вы где-то используете связывание внешних по отношению к модулю данных с платежными системами или службами доставок, то вам необходимо убедиться в корректном сохранении связей. А вообще правильнее такие связи делать через внешние ключи или мнемонические коды.
Ограничения платежных систем и служб доставок.
Раньше ограничения платежных систем и служб доставок (например, по сайтам, типам плательщика и т.п.) – были поля в таблицах соответственно платежных систем и служб доставок. Как следствие схема была не множественной и не расширяемой. Сейчас ограничения задаются с помощью новой сущности - ограничений. Они стали набираемыми для каждой службы доставки и платежной системы. Соответственно они могут быть множественными, можно расширять набор ограничений и т.д. Но следует учитывать, что это - больше не поля в таблице.
Пользовательские платежные системы.
Обратите внимание, что пользовательские обработчики платежных систем должны лежать в папке /bitrix/php_interface/include/sale_payment/. Они не могут лежать внутри /bitrix/modules/sale/. Внутри ядра продукта вы не должны ничего менять самостоятельно. Это прямо указано в документации.
Так же обратите внимание на то, что в общем случае нельзя напрямую (через include) подключать файлы из ядра продукта в свои скрипты. Если вы копировали какие-то обработчики в пользовательскую папку для изменения, то вы должны скопировать все файлы обработчика, а не подключать часть из них из ядра.
Если у вас есть вопросы, предложения, пожелания или требуется консультация - обращайтесь к нам через службу техподдержки.
s.zip
(936.42 КБ)
Можно ли задавать символьный код для платежных систем и доставок?(было бы удобно)
Какие компоненты оформления заказа будут работать на 100% с новым api?
Какие компоненты оформления заказа будут работать на calss.php?
Когда будет новая новая документация?
Единственно стоит учесть, что символьный код служб доставок сейчас задействован под совместимость со старым АПИ. Т.е. вы можете им пользоваться, если не будете пользоваться старым АПИ магазина. Для платежных систем таких ограничений нет.
У нас один компонент оформления заказа, который реально полностью поддерживается и получает все новинки и фиксы. Это - sale.order.ajax. Он сейчас переписывается для полной работы с новым магазином. Он станет объектно-ориентированным. Естественно он останется совместимым с вашими кастомными шаблонами, если таковые есть (только в этом случае у вас не будет нововведений).
Может стоит добавить внешний код для оплат и отгрузок?
заголовок настораживает
Заголовок - правда. Изменения слишком большие, чтобы быть 100% совместимыми. И не правильно это скрывать. Если вы накатите беты на ваши тестовые установки и проверите работу ваших решений, то сможете выяснить, насколько они совместимы. Если есть вопросы - мы всегда готовы ответить или обсудить какие-то моменты.
Спасибо за предупреждение о бетах.
А то мы прокараулили, похоже.
Но вот как то клиентам еще предупреждалку сделать
Решения - это ерунда
а вот многие клиенты самостоятельно обновляют Битрикс
как бы худого не вышло
Может перед конвертацией и обновлением предупреждающую табличку, чтобы получили консультацию, прежде, чем запускать?
Нам то мастерам ладно.
А вот рядовых владельцев магазинов было бы неплохо "припугнуть", они ведь на сайт разработчиков не ходят и сейчас у всех глаза горят. Дайте нам 16 релиз
Далее требуется конвертация или обновления будут не доступны.
При конвертации в начале выдаются экраны с сообщениями о том, что необходима резервная копия и т.п.
Сильно пугать тоже нельзя - иначе не перейдут на новый магазин. А тут и старых кучу багов поправлено, которые в старой версии поправить было нельзя, и новых возможностей наделано.
Далее требуется конвертация или обновления будут не доступны.
На проекте версия ядра 15.5.10, версия sale 14.11.19. Новых обновлений sale нет... Или имеется ввиду что следующие обновления sale уже на новой логике будут работать?
Вообще этот пост следовало написать раньше, а не перед самым выпуском стабильной версии.
В 16.0.6 будет дополнительно выпущено OnBeforeBasketDelete.
OnBasketDelete заработает в очередном обновлении. Тогда закроется тикет и придет уведомление.
Событие сохранения на удаление товара из корзины - OnSaleBasketItemDeleted, параметр VALUES - поля удаляемого товара.
Подскажите как теперь нужно работать с созданием заказов через API ? Где про это можно почитать?
На данный момент в 16.0.4 sale и более ранних версиях - чёрт ногу сломит при попытке передавать скидки в заказ, стоимость доставки неправильно учитывается...
Версия sale 16.0.11
В файле как понимаю вырезки из кода не полные........
Делаю Loader::includeModule('sale'), CModule::IncludeModule('sale') и т.п.
не понимаю, т.е. этот приведенный код ещё не работает? Его ещё нельзя применять?
И еще такой вопрос: зачем там надо самим указывать $payment->setField("SUM", 150); ? Разве это не должно вычисляться автоматически с учетом цен и скидок товаров заказа, а также правил корзины?
Остальные компоненты будут обновлены.
Пришлось сделать симлинк из локал, что бы с git все дружило.
в багрепорте у вас уже написано сообщение по этому поводу, тп молчит просит меня распаковать коробку заново..
т.е. одного раза им мало что наблюдается баг сразу после распаковки, ладно убью полчаса времени.
строковые есть, они лежат в другой таблице
delivery_srv заканчивается
любой чих документов (заказ,отгрузка,оплата) отслеживается одним ивентов
собственно ДО и ПОСЛЕ сохранения состояния.
const EVENT_ON_ORDER_BEFORE_SAVED = "OnSaleOrderBeforeSaved";
const EVENT_ON_ORDER_SAVED = "OnSaleOrderSaved";
вот список новых ивентов
const EVENT_ON_ORDER_PAID = "OnSaleOrderPaid";
const EVENT_ON_PAYMENT_PAID = "OnSalePaymentPaid";
const EVENT_ON_BEFORE_ORDER_DELETE = "OnSaleBeforeOrderDelete";
const EVENT_ON_ORDER_DELETED = "OnSaleOrderDeleted";
const EVENT_ON_ORDER_BEFORE_SAVED = "OnSaleOrderBeforeSaved";
const EVENT_ON_ORDER_SAVED = "OnSaleOrderSaved";
const EVENT_ON_SHIPMENT_DELIVER = "OnSaleShipmentDelivery";
const EVENT_ON_BEFORE_ORDER_CANCELED = "OnSaleBeforeOrderCanceled";
const EVENT_ON_ORDER_CANCELED = "OnSaleOrderCanceled";
const EVENT_ON_ORDER_PAID_SEND_MAIL = "OnSaleOrderPaidSendMail";
const EVENT_ON_ORDER_CANCELED_SEND_MAIL = "OnSaleOrderCancelSendEmail";
const EVENT_ON_BASKET_BEFORE_SAVED = "OnSaleBasketBeforeSaved";
const EVENT_ON_BASKET_ITEM_BEFORE_SAVED = "OnSaleBasketItemBeforeSaved";
const EVENT_ON_BASKET_ITEM_SAVED = "OnSaleBasketItemSaved";
const EVENT_ON_BASKET_SAVED = "OnSaleBasketSaved";
const EVENT_ON_SHIPMENT_TRACKING_NUMBER_CHANGE = "OnShipmentTrackingNumberChange";
const EVENT_ON_BEFORE_ORDER_STATUS_CHANGE = "OnSaleBeforeStatusOrderChange";
const EVENT_ON_ORDER_STATUS_CHANGE = "OnSaleStatusOrderChange";
const EVENT_ON_ORDER_STATUS_CHANGE_SEND_MAIL = "OnSaleOrderStatusChangeSendEmail";
+ замечен баг. Если в заказе стоит склад самовывоза он в документ отгрузки не попадает.
+еще баг. в адмнке, в заказе есть карта с складами самовывоза, так вот. Если менять его в самом заказе не происходит ничего при сохранении.
Если менять в отгрузке то меняется только в отгрузке, хотя блок в заказе "отгрузка" как бэ намекает...
"Это - не совсем правильный совет. Потому что обновленный sale.order.ajax еще не выпущен. А тот, что есть - работает в режиме совместимости"
совместимость эта сделана в методе DoSaveOrder.
Он я так полагаю будет изменен на $order->save();
"Они стали набираемыми для каждой службы доставки и платежной системы. Соответственно они могут быть множественными, можно расширять набор ограничений и т.д. Но следует учитывать, что это - больше не поля в таблице. "
да, это сериализованный массив в таблице xD
И скажите кто-нибудь как изменить у заказа свойство ато соотв метода ен могу найти в объекте заказа и подчиненных объектов ивента OnSaleOrderBeforeSaved
$phoneProp->setValue("8(000)000-00-00");
$phoneProp->save();
Хотя если они влияют на доставку то надо сохранять заказ
Тем более при сохранении записываются только измененные данные. Т.е. если вы измените только одно незначительное свойство и вызовете $order->save(), сохранится только это свойство.
Как правильно изменить стоимость заказа если есть некое свойство которое в свою очередь влияет на пересчет итоговой стоимости заказа?
И можно ли вывести в заказ список всех действующих на него скидок и наценок?
Например у нас % скидки складывается из нескольких факторов которые не могут быть описаны встроенным модулем скидки + добавляются подарки за заказ(в т.ч. от служб доставки)
При полном пересчете заказа, его стоимость будет складываться на основе актуальных данных(стоимости позиций корзины, стоимость доставки, скидки)
Если Вам требуется как-то повлиять на стоимость заказа, то лучше использовать для этого скидки(наценки).
Меня интересует, если модулем "скидки" из коробки начисляются какие-либо скидки.
Для сохраненного заказа получить данные о применении скидок на товары и правилах корзины
Все-равно Спасибо, буду хоть методы знать))
А вот вопрос про изменение свойств при создании нового заказа вопрос остается открытым. Всё что написано выше подходит если с заказом работаем вне события OnSaleOrderBeforeSaved
Если в нём сохранить заказ $order->save() то это событие вызывается заново и получаем рекурсию.
Если же в этом событии сделать сохрание свойства, точнее его значение через
$property->save() где $property это объект класса PropertyValue то происходит попытка сохранить значение в базу и т.к. ИД заказа = 0 получаем ошибку.
Если сохранять через коллекцию (PropertyCollection) то так-же ловим ошибку из текста выше.
Как быть?
По работе со свойствами заказа Вам лучше ответит Илья Дьяченко.
а)очистить номер телефона который ввел пользователь
б)выставить служебные свойства для заказа
логично сделать это ДО момента сохранения заказа...но если верить ответу ТП нужно это делать после того как заказ создался и сохранился.
Раньше же было событие onBeforeOrderAdd...why not? целостность это хорошо...но там по коду дальше всеравно заказ весь пересчитывается а поменять поля не дает
а)очистить номер телефона который ввел пользователь
б)выставить служебные свойства для заказа
простой SetValue не подходит по неизвестным причинам.
Если в конце вызывать order->save() то вызываем рекурсию
простой SetValue не подходит по неизвестным причинам.
Если в конце вызывать order->save() то вызываем рекурсию
1)тогда какие действия можно совершать с заказом через это событие? кроме вывода ошибок
2)если "сохранение должно быть вне события" соотв сохранить\изменить\удалить значение свойства можно по мнению ТП после создания заказа....
если мы вызовем после создания заказа метод $order->save() мы не попадем снова в рекурсию?
p.s. по 2му скорее нет, т.к. заказ уже осздан.
Изменения доп.сущностей можно менять в памяти и до создания заказа.
Т.е. для других сущностей заказа вызывать save не надо.
Но если корзина еще не привязана к заказу, то для сохранение изменений нужно вызывать
[Bitrix\Main\ArgumentOutOfRangeException] The value of an argument 'name=NAME' is outside the allowable range of values (100)
.../bitrix/modules/sale/lib/internals/entity.php:123#0: Bitrix\Sale\Internals\Entity->setField(string, string)
.../include/func.php:17
Подскажите, пожалуйста, в чём может быть причина.
Правильно будет
вот список новых ивентов
Осталось по-прежнему? Через CSaleBasket ?
---
А также как правильно через API передавать в корзину / заказ скидки?
Как через API передавать свойства в элементы корзины заказа? Раньше просто корзина прикреплялась к заказу и они отображались в админке в заказе.
---
Либо подскажите где сейчас это подробно расписано. Есть ли уже какая-то документация по API нового магазина?
Осталось по-прежнему? Через CSaleBasket ?
Получить позицию товара из корзины
Так же, не забывайте о том, что данные действия происходят только в памяти. Если вам необходимо сохранить ваши изменения, то нужно вызвать:
- если корзина не привязана к заказу
Было бы здорово перейти на новое API
Но когда вообще появится какая-то документация для разработчиков?
---
В частности непонятно элементарное:
1) Как добавлять свойства в элементы корзины?
2) Как вывести перечень товаров в корзине
3) Как сделать update элемента корзины?
4) Что делать с корзиной после формирования заказа - её нужно просто удалить/очистить? Каким методом?
Сейчас при формировании заказа текущая корзина отображается по-прежнему.
5) Как правильно передавать в заказ скидки? У меня получилось только, когда я в массив $products (при создании заказа) вставил DISCOUNT_PRICE - отрицательный! Иначе же получается наценка... Правильно? Так и нужно делать? Или это неправильно?
---
Позарез нужна документация по новым методам!
Предупреждения о бете не было. Пиарить начали этот новый функционал так как будто он уже стабильный, и клиент захотел новый функционал.
Сколько глюков было выявленно и до сих пор есть, я даже говорить не буду, одно количество моих тикетов может об этом сказать.
В данный момент 16.0.11 - с интернет магазином менеджерам работать невозможно. Исправления носят костыльный характер. Типо "медленно работает, давайте грузить это через аякс и пусть грузится". Вот только загрузка списка товаров в заказе >5 минут - это вин!
90% магазинов (особенно которые сделаны через API) будут иметь проблемы после обновления
Обновления в релизе
А что там? Может быть документация?
Обновлять так или иначе все равно придется. Идеально обновить копию и проверить, все ли работает.
В любом случае если вы знаете или подозреваете о каких-то потенциальных проблемах - пишите нам. Мы постараемся решить их или проконсультировать, что делать.
Мастер конвертации на втором шаге выдает список событий, которые больше не будут вызываться, для проверки того что от них зависит, накидал следующий сборщик информации:
Запускать можно в командной строке PHP в админке битрикс, либо добавить подключение пролога, и запускать как самостоятельный скрипт. Мб кому поможет
На данный момент мы поддерживаем события OnBasketUpdate, OnBeforeBasketDelete, OnBasketDelete.
А проверку конвертере забыли актуализировать список не поддерживаемых событий. Спасибо, обновим.
Что касается событий OnSaleCalculateOrderPaySystem и OnSaleCalculateOrderShoppingCart, мы не можем их поддерживать, т.к. поменялась логика подсчета стоимости. Рекомендую использовать для этого событие
Обратитесь, пожалуйста, в службу технической поддержки - вам обязательно помогут.
хотя в заказе изначально счет на полную сумму 402 руб.
номер оплаты не меняет а сумма этой оплаты становится меньше
разделение на несколько оплат не используется
это полный код. Возможно часть его вам не нужна. А возможно наоборот нужно больше. Но в целом - что-то типа этого
Тикет в тех. поддержке уже около месяца. Ничем помочь не могут.
Подскажите, пожалуйста, какие события, которые окончательно исчезли, и события, которые исчезли, но включаются через галочку поддержки устаревших событий.
Заранее спасибо!
Делаю следующий код (подключаю к init.php)
Так вот, из init.php код работает. Пытаюсь его перенести в код модуля - функцию убрать в класс (/module/include.php), регистрацию события в module/install/index.php - валится с ошибкой
Почему, и как это обойти? Как получить доступ к Bitrix\Main\Event ?
\Bitrix\Main\EventManager::getInstance()->registerEventHandler('sale','OnBeforeSaleBasketItemSetField', 'module', 'some_class, 'basketWork');
Спасибо!
1) Нужно товар класть в корзину по своему алгоритму
2) Скидку на этот товар тоже нужно расчитать по своему алгоритму
3) Иметь возможность пересчёта заказа по верхним двум пунктам из админки
Какие события исопльзовать?
Не совсем Вас понял, что Вы имеете ввиду "класть в корзину по своему алгоритму".
Вам нужно отловить факт записи элемента корзины в базу? Если так, то используйте событие OnSaleBasketItemBeforeSaved. Оно будет вызываться и из публичной части и из админки.
Во-первых, для Вашего удобства рекомендую использовать метод $basketItem->setPrice(123, true); // второй парам. как раз выставит флаг кастомности цены.
Во-вторых, лучше всего повеситься на событие OnBeforeBasketItemSetField.
1) скидка в 10%
2) скидка в 20%
и скидка 100 рублей
?
Какая версия магазина?
Обращались в техподдержку?
И еще добавлю что при создании заказа тоже самое, только с другим событием. а файл модуля sale dvizhcom\bitrix\modules\sale\lib\notify.php функция
public static function sendOrderNew(Internals\Entity $entity).. поидее ведь не долно быть так да? я просто не понимаю логику.
С другими модулями все ок
Т.к. в события объект передается по ссылке, то все изменения в памяти сохраняются после выхода из события. Соответственно данные вы не потеряете.
Что касается $order->save() или $basket->save() их нужно делать вне событий и один раз. Обычно эти методы вызываются после того как закончены все манипуляции с данным, чтобы зафиксировать все изменения в памяти.
Но Вы должны учитывать что в памяти до момента вызова save всё может поменяться. В том числе и то, что заказ может не сохраниться.
Ниже пример использования данного события для Вашего случая.
Сейчас Вам придется использовать сессию, чтобы при вызове $order->save() событие не зациклилось, но после фикса ошибки, при которой не сбрасываются данные об изменениях в заказе, проверку переменно сессии можно будет убрать.
Фикс будет доступен в ближайшем обновлении.
Вариант кода который я Вам предложил ранее используется когда требуется изменить внешние данные.
Но если Вам нужно изменить сущности заказа, то рекомендую использовать событие изменения поля OnSaleOrderSetField
Какое событие отловить, чтоб округлить цену после скидки или скидку, чтоб и в корзине и в админке в позиции применялось.
Сейчас использую событие OnBeforeSaleBasketItemSetField
В админке в итоговой стоимости - ОК
А вот в корзине и в позиции заказа в админке, округление не работает.
Вот фото:
Однако при выполнении тестового заказа в дефолтном интернет магазине Битрикса не вижу срабатывания события. (события корзины при этом срабатывают). В чем может быть дело?
У нас 3 склада отгрузки (Москва, Екатеринбург, Новосибирск)
Заказчику например нужно 10 шт. "Товар1"
Остатки на складах Москвы: 3шт, Екатеринбурга 5шт. и Новосибирск 2шт.
В заказе необходимо указать для каждого склада вариант отгрузки.
Вот пример, варианты выбора клиента сразу в одном заказе:
Москва - Отправить в Екатеринбург (внутренний транзит)
Екатеринбург - Самовывоз
Новосибирск - Отправить транспортной компанией
И вот теперь вопрос:
как сделать предварительный расчет стоимости доставки и прописать все отгрузки в заказ при сохранении?
Какие события перехватить и какие данные изменить?
Компонент обновлен и кастомизирован.
Правки только в шаблоне (ajax.php и class.php не трогал).
Самый простой вопрос — у нас есть класс \Bitrix\Sale\Order (
Отлично. А где в этом классе методы GetByID или GetList? Ну так, между прочим.
Вопрос посложнее — старое API выдает в свойствах заказа (COrder::GetById) в поле DELIVERY_ID что-то вроде "new9:profile". Внезапно. Надо ли уточнять, что старый CSaleDelivery::GetByID ничего не находит. Так и новый \Bitrix\Sale\Delivery\Services\Manager::getById падает в крайне "информативный" Exception.
Была надежда что хоть в D7 не будет адского ада. Ан нет, болезнь прогрессирует.
Документации по D7 нормальной нет, новые события сделаны через ж..пу и не понятно для каких практических целей. Длинную иерархию пространства имён не пойми для чего замутили. Сайты на Битриксе по-большинству делают фрилансеры и велосипеда от этого будет ещё больше. Продукт должен быть лёгким и быстрым в изучении. А такими мутками люди уже смотрят в сторону других движков
Ждем D8.