Битрикс вроде умеет работаеть с комплектующими, но они отображаются, как попало на сайте.
Задача: цена и остатки товара, рассчитываются из комплектующих на сайте для клиента, отображается, как товар с торг предложениями в 1С загружается как заказ из комплектующих |
в офферсах проставила связь между комплектующими
Единственный момент, у меня по одной комплектующей в товаре, если надо несколько, например 3 болта, то надо допиливать
обработчики в init.php
расчет цены, расчет остатоков, при оформлении заказа создается копия заказа из комплектующих.
AddEventHandler("catalog", "OnStoreProductUpdate", "MyOnStoreProductAddUpdate"); AddEventHandler("catalog", "OnStoreProductAdd", "MyOnStoreProductAddUpdate"); AddEventHandler("catalog", "OnPriceUpdate", "MyOnPriceAddUpdate"); AddEventHandler("catalog", "OnPriceAdd", "MyOnPriceAddUpdate"); |
function MyOnPriceAddUpdate($id,$arFields){ if(!empty($arFields["PRODUCT_ID"]) && !empty($arFields["CATALOG_GROUP_ID"]) && isset($arFields["PRICE"])){ $arFilter = Array( "IBLOCK_ID"=>IBLOCK__OFFER_ID, //"ACTIVE"=>"Y", "PROPERTY_IS_PARTS"=>5732,//товар из комплектующих равно "да" "PROPERTY_PARTS"=>$arFields["PRODUCT_ID"] ); $arSelect = Array("ID"); $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>500,"iNumPage"=>1), $arSelect); $arProducts = array(); $arPartsIds = array(); $arProductIds = array(); while($arItem = $res->GetNext()){ $res1 = CIBlockElement::GetProperty(IBLOCK__OFFER_ID, $arItem["ID"], "sort", "asc", array("CODE" => "PARTS")); $arItem["VALUES"] = array(); while ($arValue = $res1->Fetch()){ $arItem["VALUES"][] = $arValue['VALUE']; $arPartsIds[] = $arValue['VALUE']; } $arProducts[$arItem["ID"]] = $arItem; $arProductIds[] = $arItem["ID"]; } if(!empty($arPartsIds)){ $arPartsIds = array_unique($arPartsIds); $dbPrices = CPrice::GetList( array(), array( "PRODUCT_ID" => array_merge($arPartsIds,$arProductIds), "CATALOG_GROUP_ID" => $arFields["CATALOG_GROUP_ID"] ), false, array("nTopCount"=>500), array("ID","PRODUCT_ID","PRICE") ); $arPrices = array(); while($arPrice = $dbPrices->Fetch()){ $arPrices[$arPrice["PRODUCT_ID"]] = $arPrice; } // AddMessage2Log($arPrices); foreach ($arProducts as $productId => $arProduct) { $price = 0; foreach ($arProduct["VALUES"] as $partId) { if(!empty($arPrices[$partId])){ $price = $price + $arPrices[$partId]["PRICE"]; } else{ $price = 0; if(!empty($arPrices[$productId]["ID"])){ CPrice::Delete($arPrices[$productId]["ID"]); } break; } } if($price>0){ if(!empty($arPrices[$productId]["ID"])){ CPrice::Update($arPrices[$productId]["ID"],array("PRICE"=>$price)); } else{ CPrice::Add(array( "PRODUCT_ID" => $productId, "CATALOG_GROUP_ID" => $arFields["CATALOG_GROUP_ID"], "PRICE" => $price, "CURRENCY" => "RUB", "QUANTITY_FROM" => false, "QUANTITY_TO" => false )); } } } } } } |
function MyOnStoreProductAddUpdate($id,$arFields){ // AddMessage2Log($id); if(!empty($arFields["PRODUCT_ID"]) && !empty($arFields["STORE_ID"]) && isset($arFields["AMOUNT"])){ $arFilter = Array( "IBLOCK_ID"=>IBLOCK__OFFER_ID, //"ACTIVE"=>"Y", "PROPERTY_IS_PARTS"=>5732,//товар из комплектующих равно "да" "PROPERTY_PARTS"=>$arFields["PRODUCT_ID"] ); $arSelect = Array("ID"); $arFields["AMOUNT"] = intval($arFields["AMOUNT"]); $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>500,"iNumPage"=>1), $arSelect); if($arFields["AMOUNT"] == 0){ //если 0, то не проверяем другие запчасти, а ставим, что 0 $arProductIds = array(); while($arItem = $res->Fetch()){ $arProductIds[$arItem["ID"]] = $arItem["ID"]; } if(!empty($arProductIds)){ $rsStore = CCatalogStoreProduct::GetList(array(), array('PRODUCT_ID' =>$arProductIds, 'STORE_ID' => $arFields["STORE_ID"]), false, false, array('ID',"PRODUCT_ID")); while($arStore = $rsStore->Fetch()){ CCatalogStoreProduct::Update($arStore["ID"], array("AMOUNT"=>0)); unset($arProductIds[$arStore["PRODUCT_ID"]]); // AddMessage2Log($arStore); } } } else{ //AddMessage2Log($arFields); $arProducts = array(); $arPartsIds = array(); $arProductIds = array(); while($arItem = $res->Fetch()){ $res1 = CIBlockElement::GetProperty(IBLOCK__OFFER_ID, $arItem["ID"], "sort", "asc", array("CODE" => "PARTS")); $arItem["VALUES"] = array(); while ($arValue = $res1->Fetch()){ $arItem["VALUES"][] = $arValue['VALUE']; $arPartsIds[] = $arValue['VALUE']; } $arProducts[$arItem["ID"]] = $arItem; $arProductIds[] = $arItem["ID"]; } if(!empty($arProductIds) && !empty($arPartsIds)){ $arPartsIds = array_unique($arPartsIds); //AddMessage2Log(array($arProducts,$arPartsIds)); $rsStore = CCatalogStoreProduct::GetList(array(), array('PRODUCT_ID' =>array_merge($arPartsIds,$arProductIds), 'STORE_ID' => $arFields["STORE_ID"]), false, false, array("ID","PRODUCT_ID","AMOUNT")); $arStoreInfo = array(); while($arStore = $rsStore->Fetch()){ $arStoreInfo[$arStore["PRODUCT_ID"]] = array( "ID" => $arStore["ID"], "AMOUNT"=>intval($arStore["AMOUNT"]) ); } //AddMessage2Log($arStoreInfo); foreach ($arProducts as $productId => $arProduct) { $min = 1000; foreach ($arProduct["VALUES"] as $partId) { if(!empty($arStoreInfo[$partId])){ $min = ($arStoreInfo[$partId]["AMOUNT"]<$min) ? $arStoreInfo[$partId]["AMOUNT"] : $min; } else{ $min = 0; } if($min == 0){ if(!empty($arStoreInfo[$productId])){ CCatalogStoreProduct::Update($arStoreInfo[$productId]["ID"], array("AMOUNT"=>0)); } break; } } // AddMessage2Log($min); if($min>0){ if(isset($arStoreInfo[$productId]["ID"])){ //AddMessage2Log('upd'); //AddMessage2Log(array($arStoreInfo[$productId]["ID"],array("AMOUNT"=>$min))); if($min!=$arStoreInfo[$productId]["AMOUNT"]){ CCatalogStoreProduct::Update($arStoreInfo[$productId]["ID"], array("AMOUNT"=>$min)); } } else{ // AddMessage2Log('add'); CCatalogStoreProduct::Add(array( "PRODUCT_ID" => $productId, "STORE_ID" => $arFields["STORE_ID"], "AMOUNT" => $min, )); } } } } } } } |
function DeactivateProducts(&$arFields){ if(($arFields["IBLOCK_ID"] == IBLOCK__OFFER_ID)&&($arFields["ACTIVE"]=="N")){ $PROP_PRODUCT_FROM_PART = 2965; //свойство товар из комплектующих $PROP_VALUE_YES = 5733;//значение свойства "товар из комплектующих" = "да"" if(isset($arFields["PROPERTY_VALUES"][$PROP_PRODUCT_FROM_PART])){ foreach ($arFields["PROPERTY_VALUES"][$PROP_PRODUCT_FROM_PART] as $propValue) { if(!empty($propValue["VALUE"])&&($propValue["VALUE"]==$PROP_VALUE_YES)){ $arFields["ACTIVE"] = "Y"; break; } } } elseif(!empty($arFields["ID"])){ $arFilter = Array( "IBLOCK_ID"=>$arFields["IBLOCK_ID"], "ID"=>$arFields["ID"], "PROPERTY_IS_PART"=>$PROP_VALUE_YES ); $arSelect = Array("ID", "IBLOCK_ID"); $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>50,"iNumPage"=>1), $arSelect); if($arItem = $res->Fetch()){ $arFields["ACTIVE"] = "Y"; } } } } |
Main\EventManager::getInstance()->addEventHandler( 'sale', 'OnSaleOrderSaved', 'MyOnSaleOrderSaved' ); function GetBasketPropertyByCode($basketPropertyCollection, $code){ $return = false; foreach ($basketPropertyCollection as $basketProperty){ if($basketProperty->getField('CODE') == $code){ $return = $basketProperty; break; } } return $return; } function MyOnSaleOrderSaved(Main\Event $event){ $order = $event->getParameter("ENTITY"); if ($event->getParameter("IS_NEW") && CModule::IncludeModule('iblock')){ $basket = $order->getBasket(); $arProductIds = array(); $arProductIds = array(); foreach ($basket as $item) { $arProductIds[] = $item->getProductId(); } $arFilter = Array( "ID"=>$arProductIds, "PROPERTY_IS_PARTS"=>5732,//товар из комплектующих равно "да" "IBLOCK_ID"=>IBLOCK__OFFER_ID ); $arSelect = Array("ID","IBLOCK_ID"); $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>100,"iNumPage"=>1), $arSelect); $arProductsFromParts = array(); while($arItem = $res->fetch()){ $arProductsFromParts[$arItem["ID"]] = $arItem["ID"]; } if(!empty( $arProductsFromParts) && CModule::IncludeModule('sale') ){ $orderPropertyCollection = $order->getPropertyCollection(); $orderProperty = $orderPropertyCollection->getItemByOrderPropertyCode("IS_PART"); $orderProperty->setValue('Y'); $order->setField('EXTERNAL_ORDER',"Y"); $order->save(); DiscountCouponsManager::init(); $propertyCollection = $order->getPropertyCollection(); $orderNew = \Bitrix\Sale\Order::create("s3", $order->getUserId(),$order->getCurrency()); $fuser = Sale\Fuser::getIdByUserId($order->getUserId()); $basketNew = \Bitrix\Sale\Basket::create("s3"); $basketNew->setFUserId($fuser); //привязать к покупателю $orderNew->setPersonTypeId($order->getPersonTypeId()); foreach ($basket as $item) { $basketPropertyCollection = $item->getPropertyCollection(); // \Bitrix\Sale\BasketPropertyItem // $basketPropertyIsPart = GetBasketPropertyByCode($basketPropertyCollection,"IS_PART"); if(isset($arProductsFromParts[$item->getProductId()])){ $res = CIBlockElement::GetProperty(IBLOCK__OFFER_ID, $item->getProductId(), "sort", "asc", array("CODE" => "PARTS")); $arParts = []; while ($arValue = $res->Fetch()){ $arParts[] = $arValue['VALUE']; } if(!empty($arParts)){ $arFilter = Array( "ID"=>$arParts, ); $arSelect = Array("ID", "NAME","XML_ID"); $res = CIBlockElement::GetList(Array("sort"=>"asc"), $arFilter, false, Array("nPageSize"=>100,"iNumPage"=>1), $arSelect); $arNames = []; while($arItem = $res->GetNext()){ $arNames[$arItem["ID"]] = array("NAME"=>$arItem["NAME"],"XML_ID"=>$arItem["XML_ID"]); } $dbProductPrice = CPrice::GetListEx( array("ID"=>"ASC"), array("PRODUCT_ID" => $arParts,"CATALOG_GROUP_ID"=>$item->getField("PRICE_TYPE_ID")), false, false, array("PRODUCT_ID", "PRICE") ); $arPrices = []; while($arPrice = $dbProductPrice->Fetch()){ $arPrices[$arPrice["PRODUCT_ID"]] = $arPrice["PRICE"]; } foreach ($arParts as $productId) { $itemNew = $basketNew->createItem('catalog', $productId); $itemNew->setFields(array( 'NAME'=> $arNames[$productId]["NAME"] ?? "", 'PRODUCT_XML_ID'=> $arNames[$productId]["XML_ID"] ?? "", 'QUANTITY' => $item->getQuantity(), 'CURRENCY' => $item->getCurrency(), 'PRICE_TYPE_ID'=>$item->getField("PRICE_TYPE_ID"), 'LID' => "s3", 'PRICE' => $arPrices[$productId]??1, 'CUSTOM_PRICE' => 'Y', 'PRICE_TYPE_ID' => $item->getField('PRICE_TYPE_ID'), )); } } } else{ $itemNew = $basketNew->createItem('catalog', $item->getProductId()); $itemNew->setFields(array( 'NAME'=> $item->getField("NAME"), 'PRODUCT_XML_ID'=>$item->getField("PRODUCT_XML_ID"), 'PRICE_TYPE_ID'=>$item->getField("PRICE_TYPE_ID"), 'QUANTITY' => $item->getQuantity(), 'CURRENCY' => $item->getCurrency(), 'LID' => "s3", 'PRICE' => $item->getPrice(), 'CUSTOM_PRICE' => 'Y', 'PRICE_TYPE_ID' => $item->getField('PRICE_TYPE_ID'), )); } } $basketNew->save(); $orderNew->setBasket($basketNew); $orderNew->save(); $orderPropertyCollection = $order->getPropertyCollection(); $orderNewPropertyCollection = $orderNew->getPropertyCollection(); foreach ($orderPropertyCollection as $orderProperty) { if($orderProperty->getField("CODE")!="IS_PART"){ foreach ($orderNewPropertyCollection as $orderNewProperty) { if($orderNewProperty->getPropertyId() == $orderProperty->getPropertyId()){ $orderNewProperty->setValue($orderProperty->getValue()); break; } } } } //доставка $shipmentCollection = $orderNew->getShipmentCollection(); $shipment = $shipmentCollection->createItem(); $service = Delivery\Services\Manager::getById($order->getField('DELIVERY_ID')); $shipment->setFields(array( 'DELIVERY_ID' => $service['ID'], 'DELIVERY_NAME' => $service['NAME'], )); $shipmentItemCollection = $shipment->getShipmentItemCollection(); foreach ($basketNew as $item){ $shipmentItem = $shipmentItemCollection->createItem($item); $shipmentItem->setQuantity($item->getQuantity()); } //оплата $paymentCollection = $orderNew->getPaymentCollection(); $payment = $paymentCollection->createItem(\Bitrix\Sale\PaySystem\Manager::getObjectById($order->getField('PAY_SYSTEM_ID'))); //$paySystemId - ИД платежной системы $payment->setField('SUM', $orderNew->getPrice()); $order->doFinalAction(true); $result = $orderNew->save(); if ($result->isSuccess()) { CSaleOrder::Update($orderNew->getId(), array("PRICE_DELIVERY"=>$order->getDeliveryPrice())); } else { AddMessage2Log($result->getError()); } } } } |