Заполнить поля пользователя из свойства заказа, на примере ФИО

Просмотров: 4791

При создании заказа покупатель заполняет поле "ФИО". Необходимо скопировать эти данные в профиль пользователя (не путать с профилем покупателя) разбив на отдельные поля.

Работать это будет при условии что у пользователя данные поля еще не заполнены. Соответственно поля будут заполняться как у старых покупателей, которые еще не вбили эти данные, так и у новых- оформляющих заказ в первый раз.

Для оформляющих заказ в первый раз наиболее актуально, если используете фоновую регистрацию пользователя при оформлении заказа. Так как, такие пользователи в принципе не заполняют свой профиль и кроме e-mail и телефона у них поля с именем пустые.

Пользователь битрикс

Получение данных о заказе и пользователе по API

Для реализации открываем файл confirm.php который находится в шаблоне оформления заказа (sale.order.ajax). Этот файл отвечает за последний шаг заказа, когда и заказ и пользователь уже созданы.

Здесь есть массив $arResult["ORDER"] в котором имеются ID пользователя в ключе $arResult['ORDER']['USER_ID'] и ID заказа в ключе $arResult["ORDER"]['ID']

Сначала получим информацию о пользователе методом CUser::GetByID и создадим условие, проверяющее не пустое ли у пользователя поле с именем (мне достаточно только этого, но можете проверить все три поля).


$user = CUser::GetByID($arResult['ORDER']['USER_ID']);
$arUser = $user->Fetch();
if (empty($arUser['NAME'])) { 
	// тут будет срабатывать наш скрипт, если поле ИМЯ пустое
}

Теперь получаем информацию о свойствах заказа, нам нужно только поле с ФИО, которое пользователь заполняет одной строкой, при оформлении

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

Для этого пользуемся из API D7 \Bitrix\Sale\Order::load и $order->getPropertyCollection();


$order = \Bitrix\Sale\Order::load($arResult["ORDER"]['ID']);
$collection = $order->getPropertyCollection();
$dbRes = \Bitrix\Sale\PropertyValueCollection::getList([
	'select' => ['VALUE'], // Только значение
	'filter' => [
        '=ORDER_ID' => $arResult["ORDER"]['ID'], // ID этого заказа
        '=CODE' => 'FIO' // Код свойства с ФИО
    ]
]);
while ($item = $dbRes->fetch()) {
    $arUserOrderFio = explode(' ', $item['VALUE']); // Массив с ФИО
}

Теперь, у нас в массиве $arUserOrderFio ключи с фамилией именем и отчеством указанные пользователем. Массив создан с помощью explode с пробелом, в качестве разделителя, между значениями.

Обновление полей пользователя

Осталось, с помощью метода CUser::Update заполнить поля пользователя значениями ключей массива.

$user = CUser::GetByID($arResult['ORDER']['USER_ID']);
$arUser = $user->Fetch();
// Если имя пустое
if (empty($arUser['NAME'])) {

	// Данные о заказе с получением ФИО
	$order = \Bitrix\Sale\Order::load($arResult["ORDER"]['ID']);
	$collection = $order->getPropertyCollection();
	$dbRes = \Bitrix\Sale\PropertyValueCollection::getList([
		'select' => ['VALUE'], // Только значение
		'filter' => [
	        '=ORDER_ID' => $arResult["ORDER"]['ID'], // ID этого заказа
	        '=CODE' => 'FIO' // Код свойства с ФИО
	    ]
	]);
	while ($item = $dbRes->fetch()) {
	    $arUserOrderFio = explode(' ', $item['VALUE']); // Массив с ФИО
	}

	// Обновление полей пользователя
	user = new CUser;
        $fields = array(
           "LAST_NAME" => $arUserOrderFio['0'],
           "NAME" => $arUserOrderFio['1'],
           "SECOND_NAME" => $arUserOrderFio['2'],
        );
        $user->Update($arResult['ORDER']['USER_ID'], $fields);

}

На этом все. Да, по массиву $arUserOrderFio можно было пробежаться foreach-ом но это излишне.

Само собой, пользователь может не правильно вбить свое ФИО- не в том порядке который нам нужен (например ИФО), но тут остается только поделить ФИО на три отдельных поля в самом заказе и получать ровно таким же способом, но без создания массива.

Валентин 25.06.2024
Подскажите, пожалуйста, как адаптировать код, если ФИО хранится раздельно?

Также интересует момент объединения кода с этой заметкой - https://bazarow.ru/blog-note/12877/, чтобы для новых клиентов ФИО заполнялись из полей заказа.
Михаил Базаров 25.06.2024
Опишите задачу более подробно, можно прям по простому: Я хочу чтобы (подставить нужное).
Не надо сложными словами описывать, максимально топорно - по человечески.

Я, пока, не понимаю для чего вам это.
bitrix@bitrix.bitrix 26.06.2024
Тест сообщения форума  
Валентин 26.06.2024
По этой заметке. В Вашем примере ФИО в заказе хранится в одном поле. В моём случае в заказе используются 3 раздельных поля - Фамилия, Имя и Отчество (так удобнее передавать данные в транспортные компании, особенно в Почту России).

Необходимо Фамилию, Имя и Отчество из заказа передавать в соответствующие поля пользователя.


По заметке https://bazarow.ru/blog-note/12877/. С ней всё хорошо, код работает, в поле ФИО (единое) в заказе записываются данные из полей Фамилия, Имя и Отчество.
Но так как мы и в той и этой заметке редактируем файл confirm.php, хочется объединить эти две заметки в одну, то есть:
- в заказе есть три поля - Фамилия, Имя и Отчество
- в единое поле ФИО заказа записываем их вместе, делаем названием профиля
- данные из полей Фамилия, Имя и Отчество копируем в соответствующие поля пользователя (если не заполнены)
Михаил Базаров 26.06.2024
Как-то так. Проверить негде делал не глядя) но вроде бы ошибки быть не должно.
Код
// Заполняем единное поле ФИО в заказе
$order = \Bitrix\Sale\Order::load($arResult["ORDER"]['ID']);
$collection = $order->getPropertyCollection();
$dbRes = \Bitrix\Sale\PropertyValueCollection::getList([
    'select' => ['ID', 'NAME', 'CODE', 'VALUE'],
    'filter' => [
        '=ORDER_ID' => $arResult["ORDER"]['ID']
    ]
]);
while ($item = $dbRes->fetch())
{
    if ($item['CODE'] == 'FAMILIA') {
        $fullname .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'NAME') {
        $fullname .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'OTCHESTVO') {
        $fullname .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'FULL_NAME') {
        $propertyValue = $collection->getItemById($item['ID']);
        $r = $propertyValue->setField('VALUE', $fullname);
    }
}
$order->save();

// А пользователю заполняем по отдельности
// Бъем строку на массив по пробелу
$arFullname = explode(' ', $fullname);
$user = new CUser;
$fields = array(
    "LAST_NAME" =>$arFullname['0'],
    "NAME" => $arFullname['1'],
    "SECOND_NAME" => $arFullname['2'],
);
$user->Update($arResult['ORDER']['USER_ID'], $fields);

Или можно не использовать explode, просто выше (в while ($item = $dbRes->fetch())) заполнить переменные для заполнения пользователя
Михаил Базаров 26.06.2024
Варик без explode
Код
// Заполняем единное поле ФИО в заказе
$order = \Bitrix\Sale\Order::load($arResult["ORDER"]['ID']);
$collection = $order->getPropertyCollection();
$dbRes = \Bitrix\Sale\PropertyValueCollection::getList([
    'select' => ['ID', 'NAME', 'CODE', 'VALUE'],
    'filter' => [
        '=ORDER_ID' => $arResult["ORDER"]['ID']
    ]
]);
while ($item = $dbRes->fetch())
{
    if ($item['CODE'] == 'FAMILIA') {
        $familia = $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'NAME') {
        $name = $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'OTCHESTVO') {
        $otchestvo = $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'FULL_NAME') {
        $fullname = $familia  . ' ' .  $name  . ' ' .  $otchestvo;
        $propertyValue = $collection->getItemById($item['ID']);
        $r = $propertyValue->setField('VALUE', $fullname);
    }
}
$order->save();

// А пользователю заполняем по отдельности
$user = new CUser;
$fields = array(
    "LAST_NAME" =>$familia,
    "NAME" => $name,
    "SECOND_NAME" => $otchestvo,
);
$user->Update($arResult['ORDER']['USER_ID'], $fields);
Гость 26.06.2024
В моём варианте код стал таким:

Код
// Заполняем единое поле ФИО в заказе
$order = \Bitrix\Sale\Order::load($arResult["ORDER"]['ID']);
$collection = $order->getPropertyCollection();
$dbRes = \Bitrix\Sale\PropertyValueCollection::getList([
   'select' => ['ID', 'NAME', 'CODE', 'VALUE'],
   'order' => array('ID'),
   'filter' => [
     '=ORDER_ID' => $arResult["ORDER"]['ID']
   ]
]);
while ($item = $dbRes->fetch())
{
    if ($item['CODE'] == 'SECONDNAME') {
        $secondname .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'FIRSTNAME') {
        $firstname .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'MIDDLENAME') {
        $middlename .= $item['VALUE'] . ' ';
    }

    if ($item['CODE'] == 'FIO') {
$fullname = $secondname  . ' ' .  $firstname  . ' ' .  $middlename;
        $propertyValue = $collection->getItemById($item['ID']);
        $r = $propertyValue->setField('VALUE', $fullname);
    }
}
$order->save();

// А пользователю заполняем по отдельности

$user = CUser::GetByID($arResult['ORDER']['USER_ID']);
$arUser = $user->Fetch();
if (empty($arUser['NAME'])) {
    $arFullname = explode(' ', $fullname);
    $user = new CUser;
    $fields = array(
    "LAST_NAME" =>$secondname,
    "NAME" => $firstname,
    "SECOND_NAME" => $middlename,
    );
    $user->Update($arResult['ORDER']['USER_ID'], $fields);
}



Используемые значения:
SECONDNAME - Фамилия
FIRSTNAME- Имя
MIDDLENAME - Отчество
FIO - ФИО в одно поле

Также оставлена проверка на заполнение полей у пользователя
Код
if (empty($arUser['NAME'])) { }


Работает как для авторизованных, так и не авторизованных пользователей.