From c4d278a4e3f4af665088a1b64a7182ce260ab258 Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Tue, 16 Jun 2026 16:58:17 +0300 Subject: [PATCH 1/8] personType fix --- .../general/history/RetailCrmHistory_v5.php | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index 3e734aa0..eac12df2 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -599,6 +599,44 @@ public static function orderHistory(): bool $newOrder = Order::create($site, $orderCustomerExtId, $currency); + if (RetailCrmOrder::isOrderCorporate($order) + || (!empty($order['contragentType']) && in_array($order['contragentType'], ['legal-entity', 'enterpreneur'])) + ) { + $personType = $contragentTypes['legal-entity']; + $newOrder->setField('PERSON_TYPE_ID', $personType); + + $propsRemove = true; + } else { + if (isset($order['orderType']) && $order['orderType']) { + $nType = []; + $tList = RCrmActions::OrderTypesList([['LID' => $site]]); + + foreach ($tList as $type) { + if (isset($optionsOrderTypes[$type['ID']])) { + $nType[$optionsOrderTypes[$type['ID']]] = $type['ID']; + } + } + + $newOptionsOrderTypes = $nType; + + if ($newOptionsOrderTypes[$order['orderType']]) { + $personType = (int) $newOrder->getField('PERSON_TYPE_ID'); + if ($personType != $newOptionsOrderTypes[$order['orderType']] && $personType != 0) { + $propsRemove = true; + } + + $personType = $newOptionsOrderTypes[$order['orderType']]; + $newOrder->setField('PERSON_TYPE_ID', $personType); + } elseif ($personType == 0) { + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'orderType not found', + 'PERSON_TYPE_ID = 0' + ); + } + } + } + self::setManager($newOrder, $order); if (isset($buyerProfileToAppend['ID']) && isset($optionsLegalDetails['legalName'])) { @@ -684,43 +722,6 @@ public static function orderHistory(): bool $propsRemove = false; $personType = $newOrder->getField('PERSON_TYPE_ID'); - if (RetailCrmOrder::isOrderCorporate($order) - || (!empty($order['contragentType']) && in_array($order['contragentType'], ['legal-entity', 'enterpreneur'])) - ) { - $personType = $contragentTypes['legal-entity']; - $newOrder->setField('PERSON_TYPE_ID', $personType); - - $propsRemove = true; - } else { - if (isset($order['orderType']) && $order['orderType']) { - $nType = []; - $tList = RCrmActions::OrderTypesList([['LID' => $site]]); - - foreach ($tList as $type) { - if (isset($optionsOrderTypes[$type['ID']])) { - $nType[$optionsOrderTypes[$type['ID']]] = $type['ID']; - } - } - - $newOptionsOrderTypes = $nType; - - if ($newOptionsOrderTypes[$order['orderType']]) { - if ($personType != $newOptionsOrderTypes[$order['orderType']] && $personType != 0) { - $propsRemove = true; - } - - $personType = $newOptionsOrderTypes[$order['orderType']]; - $newOrder->setField('PERSON_TYPE_ID', $personType); - } elseif ($personType == 0) { - RCrmActions::eventLog( - 'RetailCrmHistory::orderHistory', - 'orderType not found', - 'PERSON_TYPE_ID = 0' - ); - } - } - } - //status if ($optionsPayStatuses[$order['status']]) { $newOrder->setField('STATUS_ID', $optionsPayStatuses[$order['status']]); From 4c075e13362255ae31b334b3d9de27f0912a8ca5 Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:01:28 +0300 Subject: [PATCH 2/8] CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4af81b3..4ca3821d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 2026-06-16 v6.8.1 +- Исправлено присвоение PERSON_TYPE_ID для $newOrder + ## 2026-06-16 v6.8.0 - Исправлены замечания по безопасности модуля. Устранены уязвимости Authentication Bypass, IDOR и SSRF. Снижены риски CSRF, XSS и Information Disclosure. Усилены проверки доступа и обработки пользовательских данных. From c1a6f450d5918c1b3b303837348383dd8582b872 Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:02:09 +0300 Subject: [PATCH 3/8] version.php --- intaro.retailcrm/install/version.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intaro.retailcrm/install/version.php b/intaro.retailcrm/install/version.php index 2ff06158..97526da3 100644 --- a/intaro.retailcrm/install/version.php +++ b/intaro.retailcrm/install/version.php @@ -1,6 +1,6 @@ '6.8.0', + 'VERSION' => '6.8.1', 'VERSION_DATE' => '2026-06-16 12:00:00' ]; From 7234926f5914ff78dce9198cc0992b076f76dbc2 Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:02:32 +0300 Subject: [PATCH 4/8] description.ru --- intaro.retailcrm/description.ru | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intaro.retailcrm/description.ru b/intaro.retailcrm/description.ru index 3761b2f5..b5f2d6f7 100644 --- a/intaro.retailcrm/description.ru +++ b/intaro.retailcrm/description.ru @@ -1 +1 @@ -- Исправлены замечания по безопасности модуля. Устранены уязвимости Authentication Bypass, IDOR и SSRF. Снижены риски CSRF, XSS и Information Disclosure. Усилены проверки доступа и обработки пользовательских данных. +- Исправлено присвоение PERSON_TYPE_ID для $newOrder From b8500edafaf6634be67a6c96cbd259312b947583 Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:03:02 +0300 Subject: [PATCH 5/8] constants.php --- intaro.retailcrm/lib/component/constants.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intaro.retailcrm/lib/component/constants.php b/intaro.retailcrm/lib/component/constants.php index 855cc6a4..f3b3851b 100644 --- a/intaro.retailcrm/lib/component/constants.php +++ b/intaro.retailcrm/lib/component/constants.php @@ -18,7 +18,7 @@ */ class Constants { - public const MODULE_VERSION = '6.8.0'; + public const MODULE_VERSION = '6.8.1'; public const CRM_PURCHASE_PRICE_NULL = 'purchasePrice_null'; public const BITRIX_USER_ID_PREFIX = 'bitrixUserId-'; public const CRM_USERS_MAP = 'crm_users_map'; From 50601151e0c1f423769758d2a99558770576839d Mon Sep 17 00:00:00 2001 From: Dmitry Igoshin <96594165+Frydabest@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:49:09 +0300 Subject: [PATCH 6/8] personType fix --- .../general/history/RetailCrmHistory_v5.php | 152 ++++++++++++------ 1 file changed, 103 insertions(+), 49 deletions(-) diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index eac12df2..a7ae67dc 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -20,6 +20,8 @@ use Bitrix\Sale\Delivery\Services\Manager; use Bitrix\Sale\Fuser; use Bitrix\Sale\Internals\PaymentTable; +use Bitrix\Sale\Internals\OrderPropsTable; +use Bitrix\Sale\Internals\OrderPropsValueTable; use Bitrix\Sale\Location\Search\Finder; use Bitrix\Sale\Order; use Bitrix\Sale\OrderUserProperties; @@ -599,44 +601,6 @@ public static function orderHistory(): bool $newOrder = Order::create($site, $orderCustomerExtId, $currency); - if (RetailCrmOrder::isOrderCorporate($order) - || (!empty($order['contragentType']) && in_array($order['contragentType'], ['legal-entity', 'enterpreneur'])) - ) { - $personType = $contragentTypes['legal-entity']; - $newOrder->setField('PERSON_TYPE_ID', $personType); - - $propsRemove = true; - } else { - if (isset($order['orderType']) && $order['orderType']) { - $nType = []; - $tList = RCrmActions::OrderTypesList([['LID' => $site]]); - - foreach ($tList as $type) { - if (isset($optionsOrderTypes[$type['ID']])) { - $nType[$optionsOrderTypes[$type['ID']]] = $type['ID']; - } - } - - $newOptionsOrderTypes = $nType; - - if ($newOptionsOrderTypes[$order['orderType']]) { - $personType = (int) $newOrder->getField('PERSON_TYPE_ID'); - if ($personType != $newOptionsOrderTypes[$order['orderType']] && $personType != 0) { - $propsRemove = true; - } - - $personType = $newOptionsOrderTypes[$order['orderType']]; - $newOrder->setField('PERSON_TYPE_ID', $personType); - } elseif ($personType == 0) { - RCrmActions::eventLog( - 'RetailCrmHistory::orderHistory', - 'orderType not found', - 'PERSON_TYPE_ID = 0' - ); - } - } - } - self::setManager($newOrder, $order); if (isset($buyerProfileToAppend['ID']) && isset($optionsLegalDetails['legalName'])) { @@ -703,6 +667,32 @@ public static function orderHistory(): bool continue; } + $currentPersonType = (int) $newOrder->getField('PERSON_TYPE_ID'); + $personType = self::resolvePersonType( + $order, + $site, + $contragentTypes, + $optionsOrderTypes, + $currentPersonType + ); + + $personTypeChanged = $personType > 0 && $personType !== $currentPersonType; + + $propsRemove = $personType > 0 && ( + RetailCrmOrder::isOrderCorporate($order) + || (!empty($order['contragentType']) + && in_array($order['contragentType'], ['legal-entity', 'enterpreneur'], true)) + || $personTypeChanged + ); + + if ($propsRemove) { + self::deleteOrderPropsExceptPersonType($newOrder, $personType); + } + + if ($personTypeChanged) { + $newOrder->setField('PERSON_TYPE_ID', $personType); + } + self::setManager($newOrder, $order); //delivery @@ -719,9 +709,6 @@ public static function orderHistory(): bool } } - $propsRemove = false; - $personType = $newOrder->getField('PERSON_TYPE_ID'); - //status if ($optionsPayStatuses[$order['status']]) { $newOrder->setField('STATUS_ID', $optionsPayStatuses[$order['status']]); @@ -768,14 +755,7 @@ public static function orderHistory(): bool $orderDump = []; $propertyCollectionArr['properties'] = $nProps; - if ($propsRemove) {//delete props - foreach ($propertyCollectionArr['properties'] as $orderProp) { - if ($orderProp['PROPS_GROUP_ID'] == 0) { - $somePropValue = $propertyCollection->getItemByOrderPropertyId($orderProp['ID']); - self::setProp($somePropValue); - } - } - + if ($propsRemove) { $orderCrm = RCrmActions::apiMethod($api, 'orderGet', __METHOD__, $order['id']); $orderDump = $order; @@ -1473,6 +1453,80 @@ public static function orderHistory(): bool return false; } + private static function resolvePersonType( + array $order, + string $site, + array $contragentTypes, + array $optionsOrderTypes, + int $currentPersonType + ): int { + if ( + RetailCrmOrder::isOrderCorporate($order) + || (!empty($order['contragentType']) + && in_array($order['contragentType'], ['legal-entity', 'enterpreneur'], true)) + ) { + return (int) ($contragentTypes['legal-entity'] ?? 0); + } + + if (empty($order['orderType'])) { + return $currentPersonType; + } + + $newOptionsOrderTypes = []; + + foreach (RCrmActions::OrderTypesList([['LID' => $site]]) as $type) { + if (isset($optionsOrderTypes[$type['ID']])) { + $newOptionsOrderTypes[$optionsOrderTypes[$type['ID']]] = (int) $type['ID']; + } + } + + if (isset($newOptionsOrderTypes[$order['orderType']])) { + return $newOptionsOrderTypes[$order['orderType']]; + } + + if ($currentPersonType === 0) { + RCrmActions::eventLog( + 'RetailCrmHistory::orderHistory', + 'orderType not found', + 'PERSON_TYPE_ID = 0' + ); + } + + return $currentPersonType; + } + + private static function deleteOrderPropsExceptPersonType(Order $order, int $personType): void + { + if ($personType <= 0 || !$order->getId()) { + return; + } + + $allowedPropertyIds = []; + $properties = OrderPropsTable::getList([ + 'select' => ['ID'], + 'filter' => ['=PERSON_TYPE_ID' => $personType], + ]); + + while ($property = $properties->fetch()) { + $allowedPropertyIds[] = (int) $property['ID']; + } + + if (empty($allowedPropertyIds)) { + return; + } + + $values = OrderPropsValueTable::getList([ + 'select' => ['ID', 'ORDER_PROPS_ID'], + 'filter' => ['=ORDER_ID' => $order->getId()], + ]); + + while ($value = $values->fetch()) { + if (!in_array((int) $value['ORDER_PROPS_ID'], $allowedPropertyIds, true)) { + OrderPropsValueTable::delete((int) $value['ID']); + } + } + } + /** * @param string $shopCode * From bb69af50a35a4d447c8686da7b8512875f375a2a Mon Sep 17 00:00:00 2001 From: Uryvskiy Dima Date: Tue, 30 Jun 2026 09:46:11 +0300 Subject: [PATCH 7/8] Fix order property cleanup on person type change --- CHANGELOG.md | 2 +- .../general/history/RetailCrmHistory_v5.php | 24 +++++++------------ intaro.retailcrm/install/version.php | 2 +- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b13bd80..ebd9a345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2026-06-26 v6.8.3 +## 2026-06-30 v6.8.3 - Исправлено присвоение PERSON_TYPE_ID для $newOrder ## 2026-06-18 v6.8.2 diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index a7ae67dc..45200fc8 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -21,7 +21,6 @@ use Bitrix\Sale\Fuser; use Bitrix\Sale\Internals\PaymentTable; use Bitrix\Sale\Internals\OrderPropsTable; -use Bitrix\Sale\Internals\OrderPropsValueTable; use Bitrix\Sale\Location\Search\Finder; use Bitrix\Sale\Order; use Bitrix\Sale\OrderUserProperties; @@ -685,14 +684,14 @@ public static function orderHistory(): bool || $personTypeChanged ); - if ($propsRemove) { - self::deleteOrderPropsExceptPersonType($newOrder, $personType); - } - if ($personTypeChanged) { $newOrder->setField('PERSON_TYPE_ID', $personType); } + if ($propsRemove) { + self::deleteOrderPropsExceptPersonType($newOrder, $personType); + } + self::setManager($newOrder, $order); //delivery @@ -1511,18 +1510,13 @@ private static function deleteOrderPropsExceptPersonType(Order $order, int $pers $allowedPropertyIds[] = (int) $property['ID']; } - if (empty($allowedPropertyIds)) { - return; - } + $propertyCollection = $order->getPropertyCollection(); - $values = OrderPropsValueTable::getList([ - 'select' => ['ID', 'ORDER_PROPS_ID'], - 'filter' => ['=ORDER_ID' => $order->getId()], - ]); + foreach ($propertyCollection as $propertyValue) { + $orderPropertyId = (int) $propertyValue->getField('ORDER_PROPS_ID'); - while ($value = $values->fetch()) { - if (!in_array((int) $value['ORDER_PROPS_ID'], $allowedPropertyIds, true)) { - OrderPropsValueTable::delete((int) $value['ID']); + if (empty($allowedPropertyIds) || !in_array($orderPropertyId, $allowedPropertyIds, true)) { + $propertyValue->delete(); } } } diff --git a/intaro.retailcrm/install/version.php b/intaro.retailcrm/install/version.php index e87f4005..f1a5af79 100644 --- a/intaro.retailcrm/install/version.php +++ b/intaro.retailcrm/install/version.php @@ -2,5 +2,5 @@ $arModuleVersion = [ 'VERSION' => '6.8.3', - 'VERSION_DATE' => '2026-06-26 12:00:00' + 'VERSION_DATE' => '2026-06-30 12:00:00' ]; From 0e44655f2c6ce9276ed4d66a96ec33fd2fdb58d0 Mon Sep 17 00:00:00 2001 From: Uryvskiy Dima Date: Tue, 30 Jun 2026 10:33:24 +0300 Subject: [PATCH 8/8] Move person type update after preliminary saves --- .../general/history/RetailCrmHistory_v5.php | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php index 45200fc8..dc6ee968 100644 --- a/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php +++ b/intaro.retailcrm/classes/general/history/RetailCrmHistory_v5.php @@ -666,6 +666,22 @@ public static function orderHistory(): bool continue; } + self::setManager($newOrder, $order); + + //delivery + if (array_key_exists('delivery', $order)) { + $itemUpdate = true; + + if (!isset($orderCrm)) { + $orderCrm = RCrmActions::apiMethod($api, 'orderGet', __METHOD__, $order['id']); + } + + if ($orderCrm) { + self::deliveryUpdate($newOrder, $optionsDelivTypes, $orderCrm['order']); + self::orderSave($newOrder); + } + } + $currentPersonType = (int) $newOrder->getField('PERSON_TYPE_ID'); $personType = self::resolvePersonType( $order, @@ -692,22 +708,6 @@ public static function orderHistory(): bool self::deleteOrderPropsExceptPersonType($newOrder, $personType); } - self::setManager($newOrder, $order); - - //delivery - if (array_key_exists('delivery', $order)) { - $itemUpdate = true; - - if (!isset($orderCrm)) { - $orderCrm = RCrmActions::apiMethod($api, 'orderGet', __METHOD__, $order['id']); - } - - if ($orderCrm) { - self::deliveryUpdate($newOrder, $optionsDelivTypes, $orderCrm['order']); - self::orderSave($newOrder); - } - } - //status if ($optionsPayStatuses[$order['status']]) { $newOrder->setField('STATUS_ID', $optionsPayStatuses[$order['status']]);