- Модуль: catalogmobile
- Путь к файлу: ~/bitrix/modules/catalogmobile/lib/Controller/StoreDocumentDetails.php
- Класс: Bitrix\CatalogMobile\Controller\StoreDocumentDetails
- Вызов: StoreDocumentDetails::updateDocumentProductRecords
private function updateDocumentProductRecords(int $documentId, array $products): void
{
$isSuccess = true;
$document = StoreDocumentTable::getList(['filter' => ['=ID' => $documentId]])->fetch();
if (!$document)
{
return;
}
$existingElements = [];
$existingElementsList = StoreDocumentElementTable::getList([
'select' => ['*'],
'filter' => ['=DOC_ID' => $documentId],
]);
while ($element = $existingElementsList->fetch())
{
$existingElements[$element['ID']] = $element;
}
/**
* Clean existing document barcodes
*/
$documentRecordIds = array_keys($existingElements);
if (!empty($documentRecordIds))
{
$existingDocumentBarcodes = StoreDocumentBarcodeTable::getList([
'select' => ['ID'],
'filter' => ['DOC_ELEMENT_ID' => $documentRecordIds],
]);
while ($existingBarcode = $existingDocumentBarcodes->fetch())
{
CCatalogStoreDocsBarcode::delete($existingBarcode['ID']);
}
}
/**
* Delete existing product elements
*/
$elementsToDelete = array_diff(
array_column($existingElements, 'ID'),
array_column($products, 'id')
);
foreach ($elementsToDelete as $elementToDelete)
{
$deleteResult = \CCatalogStoreDocsElement::delete($elementToDelete);
if ($deleteResult !== true)
{
$isSuccess = false;
}
}
/**
* Add / Update existing product elements
*/
foreach ($products as $productElement)
{
$productDto = new DocumentProductRecord($productElement);
$price = $productDto->price ?? [];
$pricePurchase = $price['purchase'] ?? [];
$priceSell = $price['sell'] ?? [];
$fields = [
'DOC_ID' => $documentId,
'ELEMENT_ID' => (int)$productDto->productId,
];
$skuEntity = null;
if ($this->checkEditPurchasePriceRights())
{
$fields['PURCHASING_PRICE'] = isset($pricePurchase['amount']) ? (float)$pricePurchase['amount'] : null;
}
else if (isset($existingElements[(int)$productDto->id]))
{
$fields['PURCHASING_PRICE'] = (float)$existingElements[(int)$productDto->id]['PURCHASING_PRICE'];
}
else
{
$skuEntity ??= ServiceContainer::getRepositoryFacade()->loadVariation($productElement['productId']);
$fields['PURCHASING_PRICE'] = $skuEntity ? $skuEntity->getField('PURCHASING_PRICE') : null;
}
if ($this->checkEditPriceRights())
{
$fields['BASE_PRICE'] = isset($priceSell['amount']) ? (float)$priceSell['amount'] : null;
}
else if (isset($existingElements[(int)$productDto->id]))
{
$fields['BASE_PRICE'] = (float)$existingElements[(int)$productDto->id]['BASE_PRICE'];
}
else
{
$skuEntity ??= ServiceContainer::getRepositoryFacade()->loadVariation($productElement['productId']);
$basePriceEntity = $skuEntity->getPriceCollection()->findBasePrice();
$fields['BASE_PRICE'] = $basePriceEntity ? $basePriceEntity->getPrice() : null;
}
$existingStoreTo = isset($existingElements[(int)$productDto->id]['STORE_TO'])
? (int)$existingElements[(int)$productDto->id]['STORE_TO']
: null;
$hasAccessToExistingStoreTo = !$existingStoreTo || $this->checkStoreAccessRights($existingStoreTo);
if ($hasAccessToExistingStoreTo)
{
$storeTo = isset($productDto->storeToId)
? (int)$productDto->storeToId
: null;
$hasStoreToAccess = !$storeTo || $this->checkStoreAccessRights($storeTo);
if (
$hasStoreToAccess
&& in_array(
$document['DOC_TYPE'],
[
StoreDocumentTable::TYPE_ARRIVAL,
StoreDocumentTable::TYPE_STORE_ADJUSTMENT,
StoreDocumentTable::TYPE_MOVING,
],
true
)
)
{
$fields['STORE_TO'] = $storeTo;
$fields['AMOUNT'] = (float)$productDto->amount;
}
}
$existingStoreFrom = isset($existingElements[(int)$productDto->id]['STORE_FROM'])
? (int)$existingElements[(int)$productDto->id]['STORE_FROM']
: null;
$hasAccessToExistingStoreFrom = !$existingStoreFrom || $this->checkStoreAccessRights($existingStoreFrom);
if ($hasAccessToExistingStoreFrom)
{
$storeFrom = isset($productDto->storeFromId)
? (int)$productDto->storeFromId
: null;
$hasStoreFromAccess = !$storeFrom || $this->checkStoreAccessRights($storeFrom);
if (
$hasStoreFromAccess
&& in_array(
$document['DOC_TYPE'],
[
StoreDocumentTable::TYPE_MOVING,
StoreDocumentTable::TYPE_DEDUCT,
],
true
)
)
{
$fields['STORE_FROM'] = $storeFrom;
$fields['AMOUNT'] = (float)$productDto->amount;
}
}
if (isset($existingElements[$productDto->id]))
{
$documentRecordId = (int)$productDto->id;
$saveResult = StoreDocumentElementTable::update($documentRecordId, $fields);
}
else
{
$saveResult = StoreDocumentElementTable::add($fields);
$documentRecordId = $saveResult->getId();
}
if (!$saveResult->isSuccess())
{
$isSuccess = false;
}
if (!empty($productDto->barcode) && !empty($documentRecordId))
{
CCatalogStoreDocsBarcode::add([
'BARCODE' => $productDto->barcode,
'DOC_ELEMENT_ID' => $documentRecordId,
]);
}
}
if (!$isSuccess)
{
$this->addNonCriticalError(
new Error(
Loc::getMessage('MOBILE_CONTROLLER_CATALOG_DETAILS_ERROR_DOCUMENT_FILES_SAVE_ERROR')
)
);
}
/**
* Update document total
*/
$elementsList = StoreDocumentElementTable::getList([
'select' => [
'ID',
'BASE_PRICE',
'PURCHASING_PRICE',
'AMOUNT',
],
'filter' => ['=DOC_ID' => $documentId],
]);
$documentTotal = 0.00;
while ($element = $elementsList->fetch())
{
$documentTotal += PriceMaths::roundPrecision((float)$element['PURCHASING_PRICE']
* (float)$element['AMOUNT']);
}
\CCatalogDocs::update($documentId, ['TOTAL' => $documentTotal]);
}