58 private const MARKING_TYPE_CODE =
'444D';
61 private $relatedEntities = array();
74 foreach ($this->relatedEntities as $type => $entityList)
76 foreach ($entityList as $entity)
80 $this->fields[
'SUM'] += $entity->getSum();
81 $this->fields[
'CURRENCY'] = $entity->getField(
'CURRENCY');
93 foreach (
$entities as $type => $entityList)
95 foreach ($entityList as $entity)
97 if (static::getSupportedRelatedEntityType() === self::SUPPORTED_ENTITY_TYPE_NONE)
102 if (static::getSupportedRelatedEntityType() === self::SUPPORTED_ENTITY_TYPE_PAYMENT
103 && !($entity instanceof
Payment)
109 if (static::getSupportedRelatedEntityType() === self::SUPPORTED_ENTITY_TYPE_SHIPMENT
126 public function getRelatedEntities()
128 if ($this->relatedEntities)
130 return $this->relatedEntities;
137 while ($entity = $dbRes->fetch())
144 $paymentClassName = $registry->getPaymentClassName();
145 $dbResPayment = $paymentClassName::getList(array(
146 'select' => array(
'ORDER_ID'),
147 'filter' => array(
'ID' => $entity[
'ENTITY_ID'])
149 if ($data = $dbResPayment->fetch())
152 $orderClass = $registry->getOrderClassName();
153 $order = $orderClass::load($data[
'ORDER_ID']);
159 $shipmentClassName = $registry->getShipmentClassName();
160 $dbResShipment = $shipmentClassName::getList(array(
161 'select' => array(
'ORDER_ID'),
162 'filter' => array(
'ID' => $entity[
'ENTITY_ID'])
164 if ($data = $dbResShipment->fetch())
167 $orderClass = $registry->getOrderClassName();
168 $order = $orderClass::load($data[
'ORDER_ID']);
180 $paymentCollection = $order->getPaymentCollection();
181 $this->relatedEntities[$entity[
'ENTITY_CHECK_TYPE']][] = $paymentCollection->getItemById($entity[
'ENTITY_ID']);
185 $shipmentCollection = $order->getShipmentCollection();
186 $this->relatedEntities[$entity[
'ENTITY_CHECK_TYPE']][] = $shipmentCollection->getItemById($entity[
'ENTITY_ID']);
190 return $this->relatedEntities;
199 $isNew = (int)$this->
getField(
'ID') === 0;
201 $result = parent::save();
202 if (!$result->isSuccess())
209 foreach ($this->relatedEntities as $checkType =>
$entities)
213 if ($entity instanceof
Payment)
223 'CHECK_ID' => $this->fields[
'ID'],
224 'ENTITY_ID' => $entity->getId(),
225 'ENTITY_TYPE' => $entityType,
226 'ENTITY_CHECK_TYPE' => $checkType,
241 'type' => static::getType(),
242 'calculated_sign' => static::getCalculatedSign(),
243 'unique_id' => $this->
getField(
'ID'),
252 if (isset($data[
'ORDER']))
254 $result[
'order'] = $data[
'ORDER'];
257 foreach ($data[
'PAYMENTS'] as $payment)
260 'entity' => $payment[
'ENTITY'],
261 'type' => $payment[
'TYPE'],
262 'is_cash' => $payment[
'IS_CASH'],
263 'sum' => $payment[
'SUM'],
264 'currency' => $payment[
'CURRENCY'],
267 if (isset($payment[
'ADDITIONAL_PARAMS']))
269 $item[
'additional_params'] = $payment[
'ADDITIONAL_PARAMS'];
272 $result[
'payments'][] = $item;
275 if (isset($data[
'PRODUCTS']))
277 foreach ($data[
'PRODUCTS'] as $product)
280 'entity' => $product[
'ENTITY'] ??
null,
281 'name' => $product[
'NAME'],
282 'base_price' => $product[
'BASE_PRICE'],
283 'price' => $product[
'PRICE'],
284 'sum' => $product[
'SUM'],
285 'currency' => $product[
'CURRENCY'],
286 'quantity' => $product[
'QUANTITY'],
287 'measure_code' => $product[
'MEASURE_CODE'] ??
'',
288 'vat' => $product[
'VAT'] ?? 0,
289 'vat_sum' => $product[
'VAT_SUM'] ?? 0,
290 'payment_object' => $product[
'PAYMENT_OBJECT'],
291 'properties' => $product[
'PROPERTIES'] ?? [],
294 if (isset($product[
'NOMENCLATURE_CODE']))
296 $item[
'nomenclature_code'] = $product[
'NOMENCLATURE_CODE'];
299 if (isset($product[
'MARKING_CODE']))
301 $item[
'marking_code'] = $product[
'MARKING_CODE'];
304 if (isset($product[
'BARCODE']))
306 $item[
'barcode'] = $product[
'BARCODE'];
309 if (!empty($product[
'DISCOUNT']))
311 $item[
'discount'] = [
312 'discount' => $product[
'DISCOUNT'][
'PRICE'],
313 'discount_type' => $product[
'DISCOUNT'][
'TYPE'],
317 if (isset($product[
'SUPPLIER_INFO']))
319 $item[
'supplier_info'] = [
320 'phones' => $product[
'SUPPLIER_INFO'][
'PHONES'] ?? [],
321 'name' => $product[
'SUPPLIER_INFO'][
'NAME'] ??
'',
322 'inn' => $product[
'SUPPLIER_INFO'][
'INN'] ??
'',
326 if (isset($product[
'ADDITIONAL_PARAMS']))
328 $item[
'additional_params'] = $product[
'ADDITIONAL_PARAMS'];
331 $result[
'items'][] = $item;
335 if (isset($data[
'DELIVERY']))
337 foreach ($data[
'DELIVERY'] as $delivery)
340 'entity' => $delivery[
'ENTITY'],
341 'name' => $delivery[
'NAME'],
342 'base_price' => $delivery[
'BASE_PRICE'],
343 'price' => $delivery[
'PRICE'],
344 'sum' => $delivery[
'SUM'],
345 'currency' => $delivery[
'CURRENCY'],
346 'quantity' => $delivery[
'QUANTITY'],
347 'vat' => $delivery[
'VAT'],
348 'vat_sum' => $delivery[
'VAT_SUM'],
349 'payment_object' => $delivery[
'PAYMENT_OBJECT'],
352 if ($delivery[
'DISCOUNT'])
354 $item[
'discount'] = [
355 'discount' => $delivery[
'DISCOUNT'][
'PRICE'],
356 'discount_type' => $delivery[
'DISCOUNT'][
'TYPE'],
360 if (isset($delivery[
'ADDITIONAL_PARAMS']))
362 $item[
'additional_params'] = $delivery[
'ADDITIONAL_PARAMS'];
365 $result[
'items'][] = $item;
369 if (isset($data[
'BUYER']))
371 if (isset($data[
'BUYER'][
'EMAIL']))
372 $result[
'client_email'] = $data[
'BUYER'][
'EMAIL'];
374 if (isset($data[
'BUYER'][
'PHONE']))
375 $result[
'client_phone'] = $data[
'BUYER'][
'PHONE'];
378 if (isset($data[
'ADDITIONAL_PARAMS']))
380 $result[
'additional_params'] = $data[
'ADDITIONAL_PARAMS'];
383 $result[
'total_sum'] = $data[
'TOTAL_SUM'];
400 private function extractDataFromEntitiesInternal(array
$entities)
414 $order = CheckManager::getOrder($entity);
415 $result[
'ORDER'] = $order;
418 if ($entity instanceof
Payment)
420 $service = $entity->getPaySystem();
421 $type = $service->getField(
'IS_CASH') ===
'Y' ? static::PAYMENT_TYPE_CASH : static::PAYMENT_TYPE_CASHLESS;
423 $result[
'PAYMENTS'][] = [
425 'IS_CASH' => $service->getField(
'IS_CASH'),
427 'SUM' => $entity->getSum(),
428 'CURRENCY' => $entity->getField(
'CURRENCY'),
431 $currency = $entity->getField(
'CURRENCY');
432 $totalSum += $entity->getSum();
434 if ($this->isShipmentExists())
440 foreach ($entity->getPayableItemCollection()->getBasketItems() as $payableItem)
443 $basketItem = $payableItem->getEntityObject();
445 $item = $this->extractDataFromBasketItem($basketItem);
448 $item[
'QUANTITY'] = (float)$payableItem->getQuantity();
450 $result[
'PRODUCTS'][] = $item;
453 foreach ($entity->getPayableItemCollection()->getShipments() as $payableItem)
455 $item = $this->extractDataFromShipment($payableItem->getEntityObject());
458 $item[
'QUANTITY'] = (float)$payableItem->getQuantity();
460 $result[
'DELIVERY'][] = $item;
464 elseif ($entity instanceof Shipment)
466 $shipmentItemCollection = $entity->getShipmentItemCollection();
467 $sellableItems = $shipmentItemCollection->getSellableItems();
470 foreach ($sellableItems as $shipmentItem)
472 $basketItem = $shipmentItem->getBasketItem();
474 $item = $this->extractDataFromBasketItem($basketItem);
478 $item[
'QUANTITY'] = 1;
479 $item[
'SUM'] = $basketItem->getPriceWithVat();
481 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
482 if ($shipmentItemStoreCollection)
484 foreach ($shipmentItemStoreCollection as $itemStore)
487 $itemStore->getMarkingCode(),
488 $basketItem->getMarkingCodeGroup()
490 $item[
'BARCODE'] = $itemStore->getBarcode();
491 $item[
'MARKING_CODE'] = $itemStore->getMarkingCode();
493 $result[
'PRODUCTS'][] = $item;
496 $diff = $shipmentItem->getQuantity() - $shipmentItemStoreCollection->count();
499 for ($i = 0; $i < $diff; $i++)
501 $item[
'NOMENCLATURE_CODE'] =
'';
502 $item[
'MARKING_CODE'] =
'';
504 $result[
'PRODUCTS'][] = $item;
512 $item[
'QUANTITY'] = (float)$shipmentItem->getQuantity();
514 $shipmentItemStoreCollection = $shipmentItem->getShipmentItemStoreCollection();
515 if (isset($shipmentItemStoreCollection[0]))
517 $item[
'BARCODE'] = $shipmentItemStoreCollection[0]->getField(
'BARCODE');
520 $result[
'PRODUCTS'][] = $item;
524 $item = $this->extractDataFromShipment($entity);
527 $result[
'DELIVERY'][] = $item;
534 $result[
'BUYER'] = array();
536 $properties = $order->getPropertyCollection();
537 $email = $properties->getUserEmail();
538 if ($email && $email->getValue())
540 $result[
'BUYER'][
'EMAIL'] = $email->getValue();
543 $phone = $properties->getPhone();
544 if ($phone && $phone->getValue())
546 $result[
'BUYER'][
'PHONE'] = $phone->getValue();
549 if (!$result[
'BUYER'])
551 $result[
'BUYER'][
'EMAIL'] = Main\Config\Option::get(
"main",
"email_from",
"admin@".$_SERVER[
'SERVER_NAME']);
555 $result[
'TOTAL_SUM'] = $totalSum;
556 $result[
'CURRENCY'] = $currency;
558 unset($shopPrices, $discounts);
565 return $basketItem->isSupportedMarkingCode();
568 private function isShipmentExists(): bool
570 foreach ($this->getEntities() as $entity)
578 foreach ($this->getRelatedEntities() as $relatedEntities)
580 foreach ($relatedEntities as $entity)
582 if ($entity instanceof Shipment)
592 private function extractDataFromShipment(Shipment $shipment) : array
594 $priceDelivery = (float)$shipment->getPrice();
595 if ($priceDelivery > 0)
598 'ENTITY' => $shipment,
599 'NAME' => Main\Localization\Loc::getMessage(
'SALE_CASHBOX_CHECK_DELIVERY'),
600 'BASE_PRICE' => (float)$shipment->getField(
'BASE_PRICE_DELIVERY'),
601 'PRICE' => (float)$shipment->getPrice(),
602 'SUM' => (float)$shipment->getPrice(),
603 'CURRENCY' => $shipment->getCurrency(),
606 'PAYMENT_OBJECT' => static::PAYMENT_OBJECT_SERVICE
609 if ($shipment->isCustomPrice())
611 $data[
'BASE_PRICE'] = $shipment->getPrice();
615 if ((
float)$shipment->getField(
'DISCOUNT_PRICE') != 0)
617 $data[
'DISCOUNT'] = array(
618 'PRICE' => $shipment->getField(
'DISCOUNT_PRICE'),
630 private function extractDataFromBasketItem(BasketItem $basketItem) : array
632 static $shopPrices = [];
634 $order = $basketItem->getBasket()->getOrder();
638 $discounts = $order->getDiscount();
641 $shopPrices = $discounts->getShowPrices();
645 $basketCode = $basketItem->getBasketCode();
646 if (!empty($shopPrices[
'BASKET'][$basketCode]))
648 $basketItem->setFieldNoDemand(
'BASE_PRICE', $shopPrices[
'BASKET'][$basketCode][
'SHOW_BASE_PRICE']);
649 $basketItem->setFieldNoDemand(
'PRICE', $shopPrices[
'BASKET'][$basketCode][
'SHOW_PRICE']);
650 $basketItem->setFieldNoDemand(
'DISCOUNT_PRICE', $shopPrices[
'BASKET'][$basketCode][
'SHOW_DISCOUNT']);
655 'ENTITY' => $basketItem,
656 'PRODUCT_ID' => $basketItem->getProductId(),
657 'NAME' => $basketItem->getField(
'NAME'),
658 'BASE_PRICE' => $basketItem->getBasePriceWithVat(),
659 'PRICE' => $basketItem->getPriceWithVat(),
660 'SUM' => $basketItem->getFinalPrice(),
661 'CURRENCY' => $basketItem->getCurrency(),
662 'QUANTITY' => (float)$basketItem->getQuantity(),
663 'MEASURE_CODE' => $basketItem->getField(
'MEASURE_CODE'),
670 $siteId = $order->getSiteId();
671 $propertiesCodes = [
'ARTNUMBER'];
672 $itemProperties = self::getCatalogPropertiesForItem($basketItem->getProductId(), $propertiesCodes, $siteId);
673 $data[
'PROPERTIES'] = $itemProperties;
677 $data[
'PROPERTIES'] = [];
680 if ($basketItem->isCustomPrice())
682 $data[
'BASE_PRICE'] = $basketItem->getPriceWithVat();
686 if ((
float)$basketItem->getDiscountPrice() != 0)
688 $data[
'DISCOUNT'] = [
689 'PRICE' => (float)$basketItem->getDiscountPrice(),
706 private static function getCatalogPropertiesForItem($itemId, $itemPropertiesCodes, $siteId): array
708 $propertiesFieldNames = [];
709 foreach ($itemPropertiesCodes as $propertyCode)
711 $propertiesFieldNames[] =
'PROPERTY_' . $propertyCode;
715 $catalogData = Admin\Product::getData([$itemId], $siteId, $propertiesFieldNames);
716 foreach ($catalogData as $item)
718 foreach ($itemPropertiesCodes as $propertyCode)
721 isset($item[
'PRODUCT_PROPS_VALUES'][
'PROPERTY_' . $propertyCode .
'_VALUE'])
722 && $item[
'PRODUCT_PROPS_VALUES'][
'PROPERTY_' . $propertyCode .
'_VALUE'] !==
' '
725 $result[$propertyCode] = $item[
'PRODUCT_PROPS_VALUES'][
'PROPERTY_' . $propertyCode .
'_VALUE'];
738 protected function buildTag1162(
string $markingCode,
string $markingCodeGroup) : string
740 [$gtin, $serial] = $this->parseMarkingCode($markingCode, $markingCodeGroup);
743 self::MARKING_TYPE_CODE.
748 return hex2bin($hex);
756 private function parseMarkingCode(
string $code,
string $group) : array
758 $gtin = mb_substr($code, 2, 14);
759 $serial = mb_substr($code, 18, $this->getSnLength($group));
761 return [$gtin, $serial];
768 private function getSnLength(
string $group) : int
770 if ((
string)$group ===
'9840')
787 for ($i = 0; $i < $size; $i++)
789 $hex = dechex(($string >> (8 * $i)) & 0xFF);
790 if (mb_strlen($hex) === 1)
795 $result = ToUpper($hex).$result;
809 for ($i = 0, $len = mb_strlen($string); $i < $len; $i++)
811 $hex = dechex(ord($string[$i]));
812 if (mb_strlen($hex) === 1)
817 $result .= ToUpper($hex);
836 $result = $this->extractDataFromEntitiesInternal(
$entities);
838 $relatedEntities = $this->getRelatedEntities();
839 if ($relatedEntities)
841 foreach ($this->relatedEntities as $type => $relatedEntities)
843 $data = $this->extractDataFromEntitiesInternal($relatedEntities);
845 if (isset($data[
'PAYMENTS']))
847 foreach ($data[
'PAYMENTS'] as $item)
849 $item[
'TYPE'] = $type;
850 $result[
'PAYMENTS'][] = $item;
854 if (isset($data[
'PRODUCTS']))
856 foreach ($data[
'PRODUCTS'] as $item)
857 $result[
'PRODUCTS'][] = $item;
860 if (isset($data[
'DELIVERY']))
862 foreach ($data[
'DELIVERY'] as $item)
863 $result[
'DELIVERY'][] = $item;
866 $result[
'TOTAL_SUM'] += $data[
'TOTAL_SUM'];
882 $calcDeliveryTax = Main\Config\Option::get(
"sale",
"COUNT_DELIVERY_TAX",
"N");
883 if ($calcDeliveryTax ===
'Y' && $service = $shipment->
getDelivery())
885 return $service->getVatId();
901 static $vatList = array();
905 $vatId = $this->getVatIdByProductId($basketItem->
getProductId());
908 $vatRate = (int)((
float)$basketItem->
getVatRate() * 100);
926 private function getVatIdByProductId($productId)
929 if (Main\Loader::includeModule(
'catalog'))
931 $dbRes = \CCatalogProduct::GetVATInfo($productId);
932 $vat = $dbRes->Fetch();
935 $vatId = (int)$vat[
'ID'];
951 if (!isset($data[
'PRODUCTS']))
953 $result->addError(
new Main\
Error(Main\Localization\
Loc::getMessage(
'SALE_CASHBOX_CHECK_ERROR_NO_PRODUCTS')));
959 foreach ($data[
'PRODUCTS'] as $product)
961 if (isset($product[
'MARKING_CODE']) && $product[
'MARKING_CODE'] ===
'')
963 if (isset($errors[$product[
'PRODUCT_ID']]))
968 $errors[$product[
'PRODUCT_ID']] =
new Main\Error(
970 'SALE_CASHBOX_CHECK_ERROR_NO_NOMENCLATURE_CODE',
972 '#PRODUCT_NAME#' => $product[
'NAME']
981 $result->addErrors($errors);
985 if (!$this->isCorrectSum($data))
987 $result->addError(
new Main\
Error(Main\Localization\
Loc::getMessage(
'SALE_CASHBOX_CHECK_ERROR_CHECK_SUM')));
990 if (!isset($data[
'BUYER']) || !$data[
'BUYER'])
992 $result->addError(
new Main\
Error(Main\Localization\
Loc::getMessage(
'SALE_CASHBOX_CHECK_ERROR_NO_BUYER_INFO')));
1002 private function isCorrectSum($data)
1007 if (!empty($data[
'PRODUCTS']))
1009 foreach ($data[
'PRODUCTS'] as $item)
1010 $productSum += $item[
'SUM'];
1013 if (!empty($data[
'DELIVERY']))
1015 foreach ($data[
'DELIVERY'] as $delivery)
1017 $productSum += $delivery[
'PRICE'];
1022 if (!empty($data[
'PAYMENTS']))
1024 foreach ($data[
'PAYMENTS'] as $payment)
1026 $paymentSum += $payment[
'SUM'];
1030 return abs($productSum - $paymentSum) < $eps;
1038 return static::SUPPORTED_ENTITY_TYPE_PAYMENT;
1046 return static::SUPPORTED_ENTITY_TYPE_PAYMENT;
1064 $result = $this->extractDataFromEntitiesInternal(
$entities);
1066 $event =
new Main\Event(
'sale', static::EVENT_ON_CHECK_PREPARE_DATA, array($result, static::getType()));
1069 if ($event->getResults())
1071 foreach ($event->getResults() as $eventResult)
1073 if ($eventResult->getType() !== Main\EventResult::ERROR)
1075 $result = $eventResult->getParameters();
1087 return static::PAYMENT_OBJECT_SERVICE;
1091 ? static::PAYMENT_OBJECT_COMMODITY_MARKING
1092 : static::PAYMENT_OBJECT_COMMODITY