%PDF- %PDF-
Direktori : /proc/self/root/home/bitrix/www/bitrix/modules/sale/lib/ |
Current File : //proc/self/root/home/bitrix/www/bitrix/modules/sale/lib/orderbase.php |
<?php /** * Bitrix Framework * @package bitrix * @subpackage sale * @copyright 2001-2012 Bitrix */ namespace Bitrix\Sale; use Bitrix\Currency; use Bitrix\Main; use Bitrix\Main\Type; use Bitrix\Main\Localization\Loc; use Bitrix\Sale\Internals; Loc::loadMessages(__FILE__); /** * Class OrderBase * @package Bitrix\Sale */ abstract class OrderBase extends Internals\Entity { /** @var Internals\Fields */ protected $calculatedFields = null; /** @var BasketBase */ protected $basketCollection; /** @var PropertyValueCollectionBase */ protected $propertyCollection; /** @var Discount $discount */ protected $discount = null; /** @var Tax $tax */ protected $tax = null; /** @var int */ protected $internalId = 0; /** @var bool $isNew */ protected $isNew = true; /** @var bool */ protected $isSaveExecuting = false; /** @var bool $isClone */ protected $isClone = false; /** @var bool $isOnlyMathAction */ protected $isOnlyMathAction = null; /** @var bool $isMeaningfulField */ protected $isMeaningfulField = false; /** @var bool $isStartField */ protected $isStartField = null; /** @var null $eventClassName */ protected static $eventClassName = null; /** @var null|string $calculateType */ protected $calculateType = null; const SALE_ORDER_CALC_TYPE_NEW = 'N'; const SALE_ORDER_CALC_TYPE_CHANGE = 'C'; const SALE_ORDER_CALC_TYPE_REFRESH = 'R'; /** * OrderBase constructor. * @param array $fields * @throws Main\ArgumentNullException */ protected function __construct(array $fields = array()) { $priceRoundedFields = ['PRICE', 'PRICE_DELIVERY', 'SUM_PAID', 'PRICE_PAYMENT', 'DISCOUNT_VALUE']; foreach ($priceRoundedFields as $code) { if (isset($fields[$code])) { $fields[$code] = PriceMaths::roundPrecision($fields[$code]); } } parent::__construct($fields); $this->isNew = (empty($fields['ID'])); } /** * Return internal index of order * * @return int */ public function getInternalId() { static $idPool = 0; if ($this->internalId == 0) { $idPool++; $this->internalId = $idPool; } return $this->internalId; } /** * Return field names that can set in \Bitrix\Sale\OrderBase::setField * * @return array */ public static function getAvailableFields() { $result = array( "LID", "PERSON_TYPE_ID", "CANCELED", "DATE_CANCELED", "EMP_CANCELED_ID", "REASON_CANCELED", "STATUS_ID", "DATE_STATUS", "EMP_STATUS_ID", "DEDUCTED", "MARKED", "DATE_MARKED", "EMP_MARKED_ID", "REASON_MARKED", "PRICE", "CURRENCY", "DISCOUNT_VALUE", "USER_ID", "DATE_INSERT", "DATE_UPDATE", "USER_DESCRIPTION", "ADDITIONAL_INFO", "COMMENTS", "TAX_VALUE", "STAT_GID", "RECURRING_ID", "LOCKED_BY", "IS_RECURRING", "DATE_LOCK", "RECOUNT_FLAG", "AFFILIATE_ID", "DELIVERY_DOC_NUM", "DELIVERY_DOC_DATE", "UPDATED_1C", "STORE_ID", "ORDER_TOPIC", "RESPONSIBLE_ID", "DATE_BILL", "DATE_PAY_BEFORE", "ACCOUNT_NUMBER", "XML_ID", "ID_1C", "VERSION_1C", "VERSION", "EXTERNAL_ORDER", "COMPANY_ID", ); return array_merge($result, static::getCalculatedFields()); } /** * Return virtual field names * * @return array */ public static function getCalculatedFields() { return array( 'PRICE_WITHOUT_DISCOUNT', 'ORDER_WEIGHT', 'DISCOUNT_PRICE', 'BASE_PRICE_DELIVERY', 'DELIVERY_LOCATION', 'DELIVERY_LOCATION_ZIP', 'TAX_LOCATION', 'TAX_PRICE', 'VAT_RATE', 'VAT_VALUE', 'VAT_SUM', 'VAT_DELIVERY', 'USE_VAT', ); } /** * @return array */ public static function getMeaningfulFields() { return array('PERSON_TYPE_ID', 'PRICE'); } /** * @param array $fields * @return mixed * @throws Main\ArgumentException * @throws Main\NotImplementedException */ private static function createOrderObject(array $fields = array()) { $registry = Registry::getInstance(static::getRegistryType()); $orderClassName = $registry->getOrderClassName(); return new $orderClassName($fields); } /** * Return registry type of class * * @throws Main\NotImplementedException */ public static function getRegistryType() { throw new Main\NotImplementedException(); } /** * Create \Bitrix\Sale\OrderBase object * * @param $siteId * @param null $userId * @param null $currency * @return Order * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\ObjectException */ public static function create($siteId, $userId = null, $currency = null) { $order = static::createOrderObject(); $order->setFieldNoDemand('LID', $siteId); if (intval($userId) > 0) $order->setFieldNoDemand('USER_ID', $userId); if ($currency == null) { $currency = Internals\SiteCurrencyTable::getSiteCurrency($siteId); } if ($currency == null) { $currency = Currency\CurrencyManager::getBaseCurrency(); } $order->setFieldNoDemand('CURRENCY', $currency); $order->setField('STATUS_ID', static::getInitialStatus()); $order->calculateType = static::SALE_ORDER_CALC_TYPE_NEW; return $order; } /** * Load order object by id * * @param $id * @return null|static * @throws Main\ArgumentNullException */ public static function load($id) { if (intval($id) <= 0) throw new Main\ArgumentNullException("id"); $filter = array( 'filter' => array('ID' => $id), 'select' => array('*'), ); $list = static::loadByFilter($filter); if (!empty($list) && is_array($list)) { return reset($list); } return null; } /** * Return object order list satisfying filter * * @param array $parameters * @return array|null * @throws Main\ArgumentException * @throws Main\NotImplementedException */ public static function loadByFilter(array $parameters) { $list = array(); $parameters = static::prepareParams($parameters); /** @var Main\DB\Result $res */ $res = static::loadFromDb($parameters); while($orderData = $res->fetch()) { $order = static::createOrderObject($orderData); $order->calculateType = static::SALE_ORDER_CALC_TYPE_CHANGE; $list[] = $order; } return (!empty($list) ? $list : null); } /** * @param $parameters * @return array */ private static function prepareParams($parameters) { $result = array( 'select' => array('*') ); if (isset($parameters['filter'])) $result['filter'] = $parameters['filter']; if (isset($parameters['limit'])) $result['limit'] = $parameters['limit']; if (isset($parameters['order'])) $result['order'] = $parameters['order']; if (isset($parameters['offset'])) $result['offset'] = $parameters['offset']; if (isset($parameters['runtime'])) $result['runtime'] = $parameters['runtime']; return $result; } /** * Load object order by account number * * @param $value * @return mixed|null * @throws Main\ArgumentException * @throws Main\ArgumentNullException * @throws Main\NotImplementedException */ public static function loadByAccountNumber($value) { if (strval(trim($value)) == '') throw new Main\ArgumentNullException("value"); $filter = array( 'filter' => array('=ACCOUNT_NUMBER' => $value), 'select' => array('*'), ); $list = static::loadByFilter($filter); if (!empty($list) && is_array($list)) { return reset($list); } return null; } /** * @param array $parameters * @return Main\DB\Result * @throws Main\NotImplementedException */ static protected function loadFromDb(array $parameters) { return static::getList($parameters); } /** * Append basket to order and refresh it * * @param BasketBase $basket * @return Result * @throws Main\NotSupportedException */ public function setBasket(BasketBase $basket) { $result = self::appendBasket($basket); if (!$this->isMathActionOnly()) { /** @var Result $r */ $r = $basket->refreshData(array('PRICE', 'QUANTITY', 'COUPONS')); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } } return $result; } /** * Append basket to order * * @param BasketBase $basket * * @return Result * @throws Main\NotSupportedException */ public function appendBasket(BasketBase $basket) { if ($this->getId()) { throw new Main\NotSupportedException(); } $basket->setOrder($this); $this->basketCollection = $basket; return new Result(); } /** * Return order basket. * * @return BasketBase */ public function getBasket() { if (!isset($this->basketCollection) || empty($this->basketCollection)) $this->basketCollection = $this->loadBasket(); return $this->basketCollection; } /** * Check basket for emptiness * * @return bool */ public function isNotEmptyBasket() { if (!isset($this->basketCollection) || empty($this->basketCollection)) $this->basketCollection = $this->loadBasket(); return !empty($this->basketCollection); } /** * Load basket appended to order * * @return BasketBase|null * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected function loadBasket() { if ((int)$this->getId() > 0) { $registry = Registry::getInstance(static::getRegistryType()); /** @var BasketBase $basketClassName */ $basketClassName = $registry->getBasketClassName(); return $basketClassName::loadItemsForOrder($this); } return null; } /** * Set value with call events on field modify * * @param $name * @param $value * @return Result * @throws Main\ArgumentException */ public function setField($name, $value) { $priceRoundedFields = array( 'PRICE' => 'PRICE', 'PRICE_DELIVERY' => 'PRICE_DELIVERY', 'SUM_PAID' => 'SUM_PAID', 'PRICE_PAYMENT' => 'PRICE_PAYMENT', 'DISCOUNT_VALUE' => 'DISCOUNT_VALUE', ); if (isset($priceRoundedFields[$name])) { $value = PriceMaths::roundPrecision($value); } if ($this->isCalculatedField($name)) { $this->calculatedFields->set($name, $value); return new Result(); } $r = parent::setField($name, $value); if (!$r->isSuccess()) { return $r; } $fields = $this->fields->getChangedValues(); if (!empty($fields) && !array_key_exists("UPDATED_1C", $fields) && $name != 'UPDATED_1C') { parent::setField("UPDATED_1C", "N"); } return $r; } /** * @internal * * Set value without call events on field modify * * @param $name * @param $value * @throws Main\ArgumentOutOfRangeException */ public function setFieldNoDemand($name, $value) { $priceRoundedFields = array( 'PRICE' => 'PRICE', 'PRICE_DELIVERY' => 'PRICE_DELIVERY', 'SUM_PAID' => 'SUM_PAID', 'PRICE_PAYMENT' => 'PRICE_PAYMENT', 'DISCOUNT_VALUE' => 'DISCOUNT_VALUE', ); if (isset($priceRoundedFields[$name])) { $value = PriceMaths::roundPrecision($value); } if ($this->isCalculatedField($name)) { $this->calculatedFields->set($name, $value); return; } if (!$this->fields->isChanged("UPDATED_1C") && $name != 'UPDATED_1C') { parent::setField("UPDATED_1C", "N"); } if ($this->isSaveExecuting === false) { if ($name === 'ID') { $this->isNew = false; } } parent::setFieldNoDemand($name, $value); } /** * Return field value * * @param $name * @return null|string */ public function getField($name) { if ($this->isCalculatedField($name)) { return $this->calculatedFields->get($name); } return parent::getField($name); } /** * @internal * * Init field * * @param $name * @param $value * @return void * @throws Main\ArgumentOutOfRangeException */ public function initField($name, $value) { if ($this->isCalculatedField($name)) { $this->calculatedFields->set($name, $value); } if ($name === 'ID') { $this->isNew = false; } parent::initField($name, $value); } /** * Return collection of order properties * * @return PropertyValueCollectionBase * @throws Main\ArgumentException * @throws Main\NotImplementedException */ public function getPropertyCollection() { if(empty($this->propertyCollection)) { $this->propertyCollection = $this->loadPropertyCollection(); } return $this->propertyCollection; } /** * @return PropertyValueCollectionBase * @throws Main\ArgumentException * @throws Main\NotImplementedException * @throws Main\ObjectPropertyException * @throws Main\SystemException */ public function loadPropertyCollection() { $registry = Registry::getInstance(static::getRegistryType()); /** @var PropertyValueCollectionBase $propertyCollectionClassName */ $propertyCollectionClassName = $registry->getPropertyValueCollectionClassName(); return $propertyCollectionClassName::load($this); } /** * @internal * * @param string $action Action. * @param PropertyValueBase $property Property. * @param null|string $name Field name. * @param null|string|int|float $oldValue Old value. * @param null|string|int|float $value New value. * @return Result */ public function onPropertyValueCollectionModify($action, PropertyValueBase $property, $name = null, $oldValue = null, $value = null) { return new Result(); } /** * Full order refresh * * @param array $select * @return Result * @throws Main\ArgumentException * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\ObjectNotFoundException */ public function refreshData($select = array()) { $result = new Result(); $isStartField = $this->isStartField(); $this->calculateType = ($this->getId() > 0 ? static::SALE_ORDER_CALC_TYPE_REFRESH : static::SALE_ORDER_CALC_TYPE_NEW); $this->refreshInternal(); if ($isStartField) { $hasMeaningfulFields = $this->hasMeaningfulField(); /** @var Result $r */ $r = $this->doFinalAction($hasMeaningfulFields); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } return $result; } /** * @param $select * @return Result * @throws Main\ArgumentException * @throws Main\ArgumentOutOfRangeException */ protected function refreshInternal() { $result = new Result(); /** @var Basket $basket */ $basket = $this->getBasket(); if (!$basket) { return $result; } /** @var Result $r */ $r = $this->setField('PRICE', $basket->getPrice()); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } return $result; } /** * Return order id * * @return int */ public function getId() { return (int)$this->getField('ID'); } /** * Return person type id of order * * @return int */ public function getPersonTypeId() { return $this->getField('PERSON_TYPE_ID'); } /** * Set person type id of order * * @param $personTypeId * * @return Result */ public function setPersonTypeId($personTypeId) { return $this->setField('PERSON_TYPE_ID', intval($personTypeId)); } /** * Return order price * * @return float */ public function getPrice() { return floatval($this->getField('PRICE')); } /** * Return paid sum * * @return float */ public function getSumPaid() { return floatval($this->getField('SUM_PAID')); } /** * @return float */ public function getDeliveryPrice() { return floatval($this->getField('PRICE_DELIVERY')); } /** * @return float */ public function getDeliveryLocation() { return $this->getField('DELIVERY_LOCATION'); } /** * @return float */ public function getTaxPrice() { return floatval($this->getField('TAX_PRICE')); } /** * @return float */ public function getTaxValue() { return floatval($this->getField('TAX_VALUE')); } /** * @return Result * @throws Main\ObjectNotFoundException */ protected function syncOrderTax() { $result = new Result(); /** @var Tax $tax */ if (!$tax = $this->getTax()) { throw new Main\ObjectNotFoundException('Entity "Tax" not found'); } $this->resetTax(); /** @var Result $r */ $r = $tax->calculate(); if ($r->isSuccess()) { $taxResult = $r->getData(); if (isset($taxResult['TAX_PRICE']) && floatval($taxResult['TAX_PRICE']) > 0) { /** @var Result $r */ $r = $this->setField('TAX_PRICE', $taxResult['TAX_PRICE']); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } if (isset($taxResult['VAT_SUM']) && floatval($taxResult['VAT_SUM']) > 0) { /** @var Result $r */ $r = $this->setField('VAT_SUM', $taxResult['VAT_SUM']); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } if (isset($taxResult['VAT_DELIVERY']) && floatval($taxResult['VAT_DELIVERY']) > 0) { /** @var Result $r */ $r = $this->setField('VAT_DELIVERY', $taxResult['VAT_DELIVERY']); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } /** @var Result $r */ $r = $this->setField('TAX_VALUE', $this->isUsedVat()? $this->getVatSum() : $this->getField('TAX_PRICE')); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } else { $result->addErrors($r->getErrors()); } return $result; } /** * Return discount price * * @return float */ public function getDiscountPrice() { return floatval($this->getField('DISCOUNT_PRICE')); } /** * Return currency * * @return string */ public function getCurrency() { return $this->getField('CURRENCY'); } /** * Return user id * * @return int */ public function getUserId() { return $this->getField('USER_ID'); } /** * Return site id * * @return null|string */ public function getSiteId() { return $this->getField('LID'); } /** * Return TRUE if VAT is used. Else return FALSE * * @return bool */ public function isUsedVat() { $useVat = $this->getField('USE_VAT'); if ($useVat === null) { $this->refreshVat(); } return $this->getField('USE_VAT') === 'Y'; } /** * Return order vat rate * * @return mixed|null */ public function getVatRate() { $vatRate = $this->getField('VAT_RATE'); if ($vatRate === null && $this->getId() > 0) { $this->refreshVat(); return $this->getField('VAT_RATE'); } return $vatRate; } /** * Return order vat sum * * @return float */ public function getVatSum() { $vatSum = $this->getField('VAT_SUM'); if ($vatSum === null && $this->getId() > 0) { $this->refreshVat(); return $this->getField('VAT_SUM'); } return $vatSum; } /** * Return TRUE if order has problems. Else return FALSE * @return null|string */ public function isMarked() { return ($this->getField('MARKED') == "Y"); } /** * Clear VAT info * @throws Main\ArgumentOutOfRangeException */ protected function resetVat() { $this->setFieldNoDemand('USE_VAT', 'N'); $this->setFieldNoDemand('VAT_RATE', 0); $this->setFieldNoDemand('VAT_SUM', 0); $this->setFieldNoDemand('VAT_DELIVERY', 0); } /** * @internal * * Recalculate VAT */ public function refreshVat() { $this->resetVat(); $vatInfo = $this->calculateVat(); if ($vatInfo && $vatInfo['VAT_RATE'] > 0) { return $this->applyCalculatedVat($vatInfo); } return new Result(); } /** * Calculate VAT * * @return array */ protected function calculateVat() { $result = array(); $basket = $this->getBasket(); if ($basket) { $result['VAT_RATE'] = $basket->getVatRate(); $result['VAT_SUM'] = $basket->getVatSum(); } return $result; } /** * @param array $vatInfo * @return Result */ private function applyCalculatedVat(array $vatInfo) { $result = new Result(); /** @var Result $r */ $r = $this->setField('USE_VAT', 'Y'); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } /** @var Result $r */ $r = $this->setField('VAT_RATE', $vatInfo['VAT_RATE']); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } /** @var Result $r */ $r = $this->setField('VAT_SUM', $vatInfo['VAT_SUM']); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } return $result; } /** * Return TRUE if order is deducted. Else return FALSE * * @return string */ public function isShipped() { return $this->getField('DEDUCTED') === 'Y'; } /** * Return TRUE if order is external. Else return FALSE * * @return bool */ public function isExternal() { return $this->getField('EXTERNAL_ORDER') == "Y"; } /** * @param $field * @return bool */ protected function isCalculatedField($field) { if ($this->calculatedFields == null ) { $this->calculatedFields = new Internals\Fields(); } return (in_array($field, static::getCalculatedFields())); } /** * @return mixed * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected static function getInitialStatus() { $registry = Registry::getInstance(static::getRegistryType()); /** @var OrderStatus $orderStatus */ $orderStatus = $registry->getOrderStatusClassName(); return $orderStatus::getInitialStatus(); } /** * @return mixed * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected static function getFinalStatus() { $registry = Registry::getInstance(static::getRegistryType()); /** @var OrderStatus $orderStatus */ $orderStatus = $registry->getOrderStatusClassName(); return $orderStatus::getFinalStatus(); } /** * Save order * * @return Result * @throws Main\ArgumentException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\ObjectException */ public function save() { if ($this->isSaveExecuting) { trigger_error("Order saving in recursion", E_USER_WARNING); } $this->isSaveExecuting = true; $result = new Result(); $id = $this->getId(); $this->isNew = ($id == 0); $r = $this->callEventOnBeforeOrderSaved(); if (!$r->isSuccess()) { $this->isSaveExecuting = false; return $r; } $r = $this->verify(); if (!$r->isSuccess()) { $this->isSaveExecuting = false; return $r; } $r = $this->onBeforeSave(); if (!$r->isSuccess()) { $this->isSaveExecuting = false; return $r; } elseif ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } if ($id > 0) { $r = $this->update(); } else { $r = $this->add(); if ($r->getId() > 0) { $id = $r->getId(); } } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } if (!$r->isSuccess()) { $this->isSaveExecuting = false; return $r; } if ($id > 0) { $result->setId($id); } $this->callEventOnSaleOrderEntitySaved(); $r = $this->saveEntities(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } /** @var Discount $discount */ $discount = $this->getDiscount(); /** @var Result $r */ $r = $discount->save(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } $r = $this->completeSaving(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } $this->callEventOnSaleOrderSaved(); $this->callDelayedEvents(); $this->onAfterSave(); $this->isNew = false; $this->isSaveExecuting = false; $this->clearChanged(); return $result; } /** * @return Result */ protected function onAfterSave() { return new Result(); } /** * @throws Main\ArgumentException * @throws Main\NotImplementedException * @return void */ protected function callDelayedEvents() { $registry = Registry::getInstance(static::getRegistryType()); $notifyClassName = $registry->getNotifyClassName(); $eventList = Internals\EventsPool::getEvents($this->getInternalId()); if ($eventList) { foreach ($eventList as $eventName => $eventData) { $event = new Main\Event('sale', $eventName, $eventData); $event->send(); $notifyClassName::callNotify($this, $eventName); } Internals\EventsPool::resetEvents($this->getInternalId()); } $notifyClassName::callNotify($this, EventActions::EVENT_ON_ORDER_SAVED); } /** * @return Result * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\ObjectException */ protected function completeSaving() { $result = new Result(); $currentDateTime = new Type\DateTime(); $updateFields = array('RUNNING' => 'N'); $changedFields = $this->fields->getChangedValues(); if ($this->isNew || ( $this->isChanged() && !array_key_exists('DATE_UPDATE', $changedFields) ) ) { $updateFields['DATE_UPDATE'] = $currentDateTime; } if ($this->isNew) { $updateFields['DATE_INSERT'] = $currentDateTime; } $this->setFieldsNoDemand($updateFields); $r = static::updateInternal($this->getId(), $updateFields); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } return $result; } /** * @return Result * @throws Main\ArgumentException * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\ObjectException * @throws Main\SystemException */ protected function add() { global $USER; $result = new Result(); $currentDateTime = new Type\DateTime(); if (!$this->getField('DATE_INSERT')) { $this->setField('DATE_INSERT', $currentDateTime); } if (!$this->getField('DATE_UPDATE')) { $this->setField('DATE_UPDATE', $currentDateTime); } $fields = $this->fields->getValues(); if (is_object($USER) && $USER->isAuthorized()) { $fields['CREATED_BY'] = $USER->getID(); $this->setFieldNoDemand('CREATED_BY', $fields['CREATED_BY']); } if (array_key_exists('REASON_MARKED', $fields) && strlen($fields['REASON_MARKED']) > 255) { $fields['REASON_MARKED'] = substr($fields['REASON_MARKED'], 0, 255); } $fields['RUNNING'] = 'Y'; $r = $this->addInternal($fields); if (!$r->isSuccess()) { return $result->addErrors($r->getErrors()); } if ($resultData = $r->getData()) { $result->setData($resultData); } $id = $r->getId(); $this->setFieldNoDemand('ID', $id); $result->setId($id); $accountNumber = $this->setAccountNumber(); if ($accountNumber) { $this->setField('ACCOUNT_NUMBER', $accountNumber); } return $result; } /** * @return Result * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ protected function update() { $result = new Result(); $fields = $this->fields->getChangedValues(); if ($this->isChanged()) { if (array_key_exists('DATE_UPDATE', $fields) && $fields['DATE_UPDATE'] === null) { unset($fields['DATE_UPDATE']); } $fields['VERSION'] = intval($this->getField('VERSION')) + 1; $this->setFieldNoDemand('VERSION', $fields['VERSION']); if (array_key_exists('REASON_MARKED', $fields) && strlen($fields['REASON_MARKED']) > 255) { $fields['REASON_MARKED'] = substr($fields['REASON_MARKED'], 0, 255); } $r = static::updateInternal($this->getId(), $fields); if (!$r->isSuccess()) { return $result->addErrors($r->getErrors()); } if ($resultData = $r->getData()) { $result->setData($resultData); } } return $result; } /** * @return void */ protected function callEventOnSaleOrderEntitySaved() { if (self::$eventClassName === null) { self::$eventClassName = static::getEntityEventName(); } if (self::$eventClassName) { $oldEntityValues = $this->fields->getOriginalValues(); if (!empty($oldEntityValues)) { $eventManager = Main\EventManager::getInstance(); if ($eventsList = $eventManager->findEventHandlers('sale', 'On'.self::$eventClassName.'EntitySaved')) { /** @var Main\Event $event */ $event = new Main\Event('sale', 'On'.self::$eventClassName.'EntitySaved', array( 'ENTITY' => $this, 'VALUES' => $oldEntityValues, )); $event->send(); } } } } /** * @return void */ protected function callEventOnSaleOrderSaved() { $eventManager = Main\EventManager::getInstance(); if ($eventsList = $eventManager->findEventHandlers('sale', EventActions::EVENT_ON_ORDER_SAVED)) { $event = new Main\Event('sale', EventActions::EVENT_ON_ORDER_SAVED, array( 'ENTITY' => $this, 'IS_NEW' => $this->isNew, 'IS_CHANGED' => $this->isChanged(), 'VALUES' => $this->fields->getOriginalValues(), )); $event->send(); } } /** * @return Result */ protected function callEventOnBeforeOrderSaved() { $result = new Result(); /** @var array $oldEntityValues */ $oldEntityValues = $this->fields->getOriginalValues(); $eventManager = Main\EventManager::getInstance(); if ($eventsList = $eventManager->findEventHandlers('sale', EventActions::EVENT_ON_ORDER_BEFORE_SAVED)) { /** @var Main\Entity\Event $event */ $event = new Main\Event('sale', EventActions::EVENT_ON_ORDER_BEFORE_SAVED, array( 'ENTITY' => $this, 'VALUES' => $oldEntityValues )); $event->send(); if ($event->getResults()) { /** @var Main\EventResult $eventResult */ foreach($event->getResults() as $eventResult) { if($eventResult->getType() == Main\EventResult::ERROR) { $errorMsg = new ResultError(Main\Localization\Loc::getMessage('SALE_EVENT_ON_BEFORE_ORDER_SAVED_ERROR'), 'SALE_EVENT_ON_BEFORE_ORDER_SAVED_ERROR'); if ($eventResultData = $eventResult->getParameters()) { if (isset($eventResultData) && $eventResultData instanceof ResultError) { /** @var ResultError $errorMsg */ $errorMsg = $eventResultData; } } $result->addError($errorMsg); } } } } return $result; } /** * @return Result */ protected function saveEntities() { $result = new Result(); /** @var BasketBase $basket */ $basket = $this->getBasket(); /** @var Result $r */ $r = $basket->save(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } /** @var Tax $tax */ $tax = $this->getTax(); /** @var Result $r */ $r = $tax->save(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } /** @var PropertyValueCollectionBase $propertyCollection */ $propertyCollection = $this->getPropertyCollection(); /** @var Result $r */ $r = $propertyCollection->save(); if (!$r->isSuccess()) { $result->addWarnings($r->getErrors()); } return $result; } /** * Set account number. * * @return mixed * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\SystemException */ protected function setAccountNumber() { $accountNumber = Internals\AccountNumberGenerator::generateForOrder($this); if ($accountNumber !== false) { static::updateInternal($this->getId(), ['ACCOUNT_NUMBER' => $accountNumber]); } return $accountNumber; } /** * Set VAT sum * * @param $price */ public function setVatSum($price) { $this->setField('VAT_SUM', $price); } /** * Set VAT delivery sum * * @param $price */ public function setVatDelivery($price) { $this->setField('VAT_DELIVERY', $price); } /** * Return date order insert * * @return mixed */ public function getDateInsert() { return $this->getField('DATE_INSERT'); } /** * Return value: OrderBase::SALE_ORDER_CALC_TYPE_REFRESH, OrderBase::SALE_ORDER_CALC_TYPE_CHANGE, OrderBase::SALE_ORDER_CALC_TYPE_NEW * * @return null|string */ public function getCalculateType() { return $this->calculateType; } /** * Modify order field. * * @param string $name Field name. * @param mixed|string|int|float $oldValue Old value. * @param mixed|string|int|float $value New value. * @return Result * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException * @throws Main\ObjectNotFoundException */ protected function onFieldModify($name, $oldValue, $value) { global $USER; $result = new Result(); if ($name == "PRICE") { /** @var Result $r */ $r = $this->refreshVat(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } } elseif ($name == "CURRENCY") { throw new Main\NotImplementedException('field CURRENCY'); } elseif ($name == "CANCELED") { $event = new Main\Event('sale', EventActions::EVENT_ON_BEFORE_ORDER_CANCELED, array( 'ENTITY' => $this )); $event->send(); if ($event->getResults()) { /** @var Main\EventResult $eventResult */ foreach($event->getResults() as $eventResult) { if($eventResult->getType() == Main\EventResult::ERROR) { $errorMsg = new ResultError( Main\Localization\Loc::getMessage('SALE_EVENT_ON_BEFORE_ORDER_CANCELED_ERROR'), 'SALE_EVENT_ON_BEFORE_ORDER_CANCELED_ERROR' ); if ($eventResultData = $eventResult->getParameters()) { if (isset($eventResultData) && $eventResultData instanceof ResultError) { /** @var ResultError $errorMsg */ $errorMsg = $eventResultData; } } $result->addError($errorMsg); } } } if (!$result->isSuccess()) { return $result; } $r = $this->onOrderModify($name, $oldValue, $value); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } $this->setField('DATE_CANCELED', new Type\DateTime()); if (is_object($USER) && $USER->isAuthorized()) $this->setField('EMP_CANCELED_ID', $USER->getID()); Internals\EventsPool::addEvent( $this->getInternalId(), EventActions::EVENT_ON_ORDER_CANCELED, array('ENTITY' => $this) ); Internals\EventsPool::addEvent( $this->getInternalId(), EventActions::EVENT_ON_ORDER_CANCELED_SEND_MAIL, array('ENTITY' => $this) ); } elseif ($name == "USER_ID") { throw new Main\NotImplementedException('field USER_ID'); } elseif($name == "MARKED") { if ($oldValue != "Y") { $this->setField('DATE_MARKED', new Type\DateTime()); if ($USER->isAuthorized()) $this->setField('EMP_MARKED_ID', $USER->getID()); } elseif ($value == "N") { $this->setField('REASON_MARKED', ''); } } elseif ($name == "STATUS_ID") { $event = new Main\Event('sale', EventActions::EVENT_ON_BEFORE_ORDER_STATUS_CHANGE, array( 'ENTITY' => $this, 'VALUE' => $value, 'OLD_VALUE' => $oldValue, )); $event->send(); if ($event->getResults()) { /** @var Main\EventResult $eventResult */ foreach($event->getResults() as $eventResult) { if($eventResult->getType() == Main\EventResult::ERROR) { $errorMsg = new ResultError( Main\Localization\Loc::getMessage('SALE_EVENT_ON_BEFORE_ORDER_STATUS_CHANGE_ERROR'), 'SALE_EVENT_ON_BEFORE_ORDER_STATUS_CHANGE_ERROR' ); if ($eventResultData = $eventResult->getParameters()) { if (isset($eventResultData) && $eventResultData instanceof ResultError) { /** @var ResultError $errorMsg */ $errorMsg = $eventResultData; } } $result->addError($errorMsg); } } } if (!$result->isSuccess()) { return $result; } $this->setField('DATE_STATUS', new Type\DateTime()); if (is_object($USER) && $USER->isAuthorized()) { $this->setField('EMP_STATUS_ID', $USER->GetID()); } Internals\EventsPool::addEvent($this->getInternalId(), EventActions::EVENT_ON_ORDER_STATUS_CHANGE, array( 'ENTITY' => $this, 'VALUE' => $value, 'OLD_VALUE' => $oldValue, )); Internals\EventsPool::addEvent($this->getInternalId(), EventActions::EVENT_ON_ORDER_STATUS_CHANGE_SEND_MAIL, array( 'ENTITY' => $this, 'VALUE' => $value, 'OLD_VALUE' => $oldValue, )); if ($this->isStatusChangedOnPay($value, $oldValue)) { Internals\EventsPool::addEvent($this->getInternalId(), EventActions::EVENT_ON_ORDER_STATUS_ALLOW_PAY_CHANGE, array( 'ENTITY' => $this, 'VALUE' => $value, 'OLD_VALUE' => $oldValue, )); } } return $result; } /** * @param $name * @param $oldValue * @param $value * @return Result */ protected function onOrderModify($name, $oldValue, $value) { return new Result(); } /** * Modify basket. * * @param string $action Action. * @param BasketItemBase $basketItem Basket item. * @param null|string $name Field name. * @param null|string|int|float $oldValue Old value. * @param null|string|int|float $value New value. * @return Result * @throws Main\NotImplementedException * @throws Main\NotSupportedException * @throws Main\ObjectNotFoundException */ public function onBasketModify($action, BasketItemBase $basketItem, $name = null, $oldValue = null, $value = null) { $result = new Result(); if ($action === EventActions::DELETE) { /** @var Result $r */ $r = $this->refreshVat(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } if ($tax = $this->getTax()) { $tax->resetTaxList(); } /** @var Result $result */ $r = $this->refreshOrderPrice(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } return $result; } elseif ($action !== EventActions::UPDATE) { return $result; } if ($name == "QUANTITY" || $name == "PRICE") { /** @var Result $result */ $r = $this->refreshOrderPrice(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } elseif ($name == "CURRENCY") { if ($value != $this->getField("CURRENCY")) { throw new Main\NotSupportedException("CURRENCY"); } } return $result; } /** * @internal * @return Result */ public function onBeforeBasketRefresh() { return new Result(); } /** * @internal * @return Result */ public function onAfterBasketRefresh() { return new Result(); } /** * Get the entity of taxes * * @return Tax */ public function getTax() { if ($this->tax === null) { $this->tax = $this->loadTax(); } return $this->tax; } /** * @internal * * Return TRUE if order is new. Else return FALSE * * @return null|bool */ public function isNew() { return $this->isNew; } /** * Reset the value of taxes * * @internal */ public function resetTax() { $this->setFieldNoDemand('TAX_PRICE', 0); $this->setFieldNoDemand('TAX_VALUE', 0); } /** * Return TRUE if order is changed. Else return FALSE * * @return bool */ public function isChanged() { if (parent::isChanged()) return true; /** @var PropertyValueCollectionBase $propertyCollection */ if ($propertyCollection = $this->getPropertyCollection()) { if ($propertyCollection->isChanged()) { return true; } } /** @var BasketBase $basket */ if ($basket = $this->getBasket()) { if ($basket->isChanged()) { return true; } } return false; } /** * @internal * * Reset flag of order change * * @return void */ public function clearChanged() { parent::clearChanged(); if ($basket = $this->getBasket()) { $basket->clearChanged(); } if ($property = $this->getPropertyCollection()) { $property->clearChanged(); } } /** * Return TRUE, if this order is cloned. Else return FALSE * * @return bool */ public function isClone() { return $this->isClone; } /** * Return TRUE, if order is payed. Else return FALSE * * @return bool */ public function isPaid() { return $this->getField('PAYED') === "Y"; } /** * Return TRUE, if order is allowed delivery. Else return FALSE * * @return bool */ public function isAllowDelivery() { return $this->getField('ALLOW_DELIVERY') === "Y"; } /** * Return TRUE, if order is canceled. Else return FALSE * * @return bool */ public function isCanceled() { return $this->getField('CANCELED') === "Y"; } /** * Return order hash * * @return mixed */ public function getHash() { /** @var Main\Type\DateTime $dateInsert */ $dateInsert = $this->getDateInsert()->setTimeZone(new \DateTimeZone("Europe/Moscow")); $timestamp = $dateInsert->getTimestamp(); return md5( $this->getId(). $timestamp. $this->getUserId(). $this->getField('ACCOUNT_NUMBER') ); } /** * Verify object to correctness * * @return Result */ public function verify() { $result = new Result(); /** @var BasketBase $basket */ if ($basket = $this->getBasket()) { $r = $basket->verify(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } /** @var PropertyValueCollectionBase $propertyCollection */ if ($propertyCollection = $this->getPropertyCollection()) { $r = $propertyCollection->verify(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } return $result; } /** * Get order information * * @param array $parameters * @throws Main\NotImplementedException * @return Main\DB\Result */ public static function getList(array $parameters = array()) { throw new Main\NotImplementedException(); } /** * Return tax location * * @return null|string */ public function getTaxLocation() { if (strval(($this->getField('TAX_LOCATION')) == "")) { /** @var PropertyValueCollectionBase $propertyCollection */ $propertyCollection = $this->getPropertyCollection(); if ($property = $propertyCollection->getTaxLocation()) { $this->setField('TAX_LOCATION', $property->getValue()); } } return $this->getField('TAX_LOCATION'); } /** * Return TRUE if calculations are based on current values. Data from the provider is not requested. Else return false * * @return bool */ public function isMathActionOnly() { return $this->isOnlyMathAction; } /** * @return bool */ public function hasMeaningfulField() { return $this->isMeaningfulField; } /** * Reset order flags: \Bitrix\Sale\OrderBase::$isStartField, \Bitrix\Sale\OrderBase::$isMeaningfulField * * @return void */ public function clearStartField() { $this->isStartField = null; $this->isMeaningfulField = false; } /** * @param bool $isMeaningfulField * @return bool */ public function isStartField($isMeaningfulField = false) { if ($this->isStartField === null) { $this->isStartField = true; } else { $this->isStartField = false; } if ($isMeaningfulField === true) { $this->isMeaningfulField = true; } return $this->isStartField; } /** * @internal * * Set TRUE if calculations should be held on current values. Data from the provider is not requested * * @param bool $value */ public function setMathActionOnly($value = false) { $this->isOnlyMathAction = $value; } /** * @internal * * Delete order without demands. * * @param $id * @return Result * @throws Main\NotImplementedException */ public static function deleteNoDemand($id) { $result = new Result(); if (!static::isExists($id)) { $result->addError(new ResultError(Loc::getMessage('SALE_ORDER_ENTITY_NOT_FOUND'), 'SALE_ORDER_ENTITY_NOT_FOUND')); return $result; } /** @var Result $deleteResult */ $deleteResult = static::deleteEntitiesNoDemand($id); if (!$deleteResult->isSuccess()) { $result->addErrors($deleteResult->getErrors()); return $result; } $r = static::deleteInternal($id); if (!$r->isSuccess()) $result->addErrors($r->getErrors()); static::deleteExternalEntities($id); return $result; } /** * Delete order * * @param int $id Order id. * @return Result * @throws Main\ArgumentNullException */ public static function delete($id) { $result = new Result(); $registry = Registry::getInstance(static::getRegistryType()); /** @var OrderBase $orderClassName */ $orderClassName = $registry->getOrderClassName(); if (!$order = $orderClassName::load($id)) { $result->addError(new ResultError(Loc::getMessage('SALE_ORDER_ENTITY_NOT_FOUND'), 'SALE_ORDER_ENTITY_NOT_FOUND')); return $result; } /** @var Notify $notifyClassName */ $notifyClassName = $registry->getNotifyClassName(); $notifyClassName::setNotifyDisable(true); /** @var Result $r */ $r = $order->setField('CANCELED', 'Y'); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } static::deleteEntities($order); $event = new Main\Event( 'sale', EventActions::EVENT_ON_BEFORE_ORDER_DELETE, array('ENTITY' => $order) ); $event->send(); foreach ($event->getResults() as $eventResult) { $return = null; if ($eventResult->getType() == Main\EventResult::ERROR) { if ($eventResultData = $eventResult->getParameters()) { if (isset($eventResultData) && $eventResultData instanceof ResultError) { /** @var ResultError $errorMsg */ $errorMsg = $eventResultData; } } if (!isset($errorMsg)) $errorMsg = new ResultError('EVENT_ORDER_DELETE_ERROR'); $result->addError($errorMsg); return $result; } } /** @var Result $r */ $r = $order->save(); if ($r->isSuccess()) { /** @var Main\Entity\DeleteResult $r */ $r = static::deleteInternal($id); if ($r->isSuccess()) static::deleteExternalEntities($id); } else { $result->addErrors($r->getErrors()); } $notifyClassName::setNotifyDisable(false); $event = new Main\Event( 'sale', EventActions::EVENT_ON_ORDER_DELETED, array('ENTITY' => $order, 'VALUE' => $r->isSuccess()) ); $event->send(); $result->addData(array('ORDER' => $order)); return $result; } /** * @param OrderBase $order * @return void */ protected static function deleteEntities(OrderBase $order) { /** @var BasketBase $basketCollection */ if ($basketCollection = $order->getBasket()) { /** @var BasketItemBase $basketItem */ foreach ($basketCollection as $basketItem) { $basketItem->delete(); } } /** @var PropertyValueCollectionBase $propertyCollection */ if ($propertyCollection = $order->getPropertyCollection()) { /** @var PropertyValue $property */ foreach ($propertyCollection as $property) { $property->delete(); } } } /** * @param $id * @return bool * @throws Main\NotImplementedException */ protected static function isExists($id) { $dbRes = static::getList(array('filter' => array('ID' => $id))); if ($dbRes->fetch()) return true; return false; } /** * @deprecated Use OrderStatus::isAllowPay instead * * @return bool * @throws Main\ArgumentException * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ public function isAllowPay() { $registry = Registry::getInstance(static::getRegistryType()); /** @var OrderStatus $orderClassName */ $orderClassName = $registry->getOrderStatusClassName(); return $orderClassName::isAllowPay($this->getField('STATUS_ID')); } /** * @param $orderId */ protected static function deleteExternalEntities($orderId) { return; } /** * @param $oderId * @return Result */ protected static function deleteEntitiesNoDemand($oderId) { $registry = Registry::getInstance(static::getRegistryType()); /** @var BasketBase $basketClassName */ $basketClassName = $registry->getBasketClassName(); $r = $basketClassName::deleteNoDemand($oderId); if (!$r->isSuccess()) return $r; /** @var PropertyValueCollectionBase $propertyValueCollectionClassName */ $propertyValueCollectionClassName = $registry->getPropertyValueCollectionClassName(); $propertyValueCollectionClassName::deleteNoDemand($oderId); if (!$r->isSuccess()) return $r; return new Result(); } /** * Return discount object * * @return Discount */ public function getDiscount() { if ($this->discount === null) { $this->discount = $this->loadDiscount(); } return $this->discount; } /** * @return Tax * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected function loadTax() { $registry = Registry::getInstance(static::getRegistryType()); /** @var Tax $taxClassName */ $taxClassName = $registry->getTaxClassName(); return $taxClassName::load($this); } /** * @return DiscountBase * @throws Main\ArgumentException * @throws Main\NotImplementedException */ protected function loadDiscount() { $registry = Registry::getInstance(static::getRegistryType()); /** @var Discount $discountClassName */ $discountClassName = $registry->getDiscountClassName(); return $discountClassName::buildFromOrder($this); } /** * @return Result */ private function refreshOrderPrice() { return $this->setField("PRICE", $this->calculatePrice()); } /** * @return float */ protected function calculatePrice() { $basket = $this->getBasket(); $taxPrice = !$this->isUsedVat() ? $this->getField('TAX_PRICE') : 0; return $basket->getPrice() + $taxPrice; } /** * @return Result */ protected function onBeforeSave() { return new Result(); } /** * @param bool $hasMeaningfulField * @return Result * @throws Main\ArgumentNullException * @throws Main\ObjectNotFoundException */ public function doFinalAction($hasMeaningfulField = false) { $result = new Result(); $orderInternalId = $this->getInternalId(); $r = Internals\ActionEntity::runActions($orderInternalId); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } if (!$hasMeaningfulField) { $this->clearStartField(); return $result; } if ($r->hasWarnings()) { $result->addWarnings($r->getWarnings()); } $currentIsMathActionOnly = $this->isMathActionOnly(); $basket = $this->getBasket(); if ($basket) { $this->setMathActionOnly(true); if (self::$eventClassName === null) { self::$eventClassName = static::getEntityEventName(); } if (self::$eventClassName) { $eventManager = Main\EventManager::getInstance(); $eventsList = $eventManager->findEventHandlers('sale', 'OnBefore'.self::$eventClassName.'FinalAction'); if (!empty($eventsList)) { $event = new Main\Event('sale', 'OnBefore'.self::$eventClassName.'FinalAction', array( 'ENTITY' => $this, 'HAS_MEANINGFUL_FIELD' => $hasMeaningfulField, 'BASKET' => $basket, )); $event->send(); if ($event->getResults()) { /** @var Main\EventResult $eventResult */ foreach($event->getResults() as $eventResult) { if($eventResult->getType() == Main\EventResult::ERROR) { $errorMsg = new ResultError( Main\Localization\Loc::getMessage( 'SALE_EVENT_ON_BEFORE_'.strtoupper(self::$eventClassName).'_FINAL_ACTION_ERROR' ), 'SALE_EVENT_ON_BEFORE_'.strtoupper(self::$eventClassName).'_FINAL_ACTION_ERROR' ); $eventResultData = $eventResult->getParameters(); if ($eventResultData) { if (isset($eventResultData) && $eventResultData instanceof ResultError) { /** @var ResultError $errorMsg */ $errorMsg = $eventResultData; } } $result->addError($errorMsg); } } } } if (!$result->isSuccess()) { return $result; } } // discount $discount = $this->getDiscount(); $r = $discount->calculate(); if (!$r->isSuccess()) { // $this->clearStartField(); // $result->addErrors($r->getErrors()); // return $result; } if ($r->isSuccess() && ($discountData = $r->getData()) && !empty($discountData) && is_array($discountData)) { /** @var Result $r */ $r = $this->applyDiscount($discountData); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } } /** @var Tax $tax */ $tax = $this->getTax(); /** @var Result $r */ $r = $tax->refreshData(); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); return $result; } $taxResult = $r->getData(); $taxChanged = false; if (isset($taxResult['TAX_PRICE']) && floatval($taxResult['TAX_PRICE']) >= 0) { if (!$this->isUsedVat()) { $taxChanged = $this->getField('TAX_PRICE') !== $taxResult['TAX_PRICE']; if ($taxChanged) { $this->setField('TAX_PRICE', $taxResult['TAX_PRICE']); $this->refreshOrderPrice(); } } } if (array_key_exists('VAT_SUM', $taxResult)) { if ($this->isUsedVat()) { $this->setField('VAT_SUM', $taxResult['VAT_SUM']); } } if ($taxChanged || $this->isUsedVat()) { $taxValue = $this->isUsedVat()? $this->getVatSum() : $this->getField('TAX_PRICE'); if (floatval($taxValue) != floatval($this->getField('TAX_VALUE'))) { $this->setField('TAX_VALUE', floatval($taxValue)); } } } if (!$currentIsMathActionOnly) $this->setMathActionOnly(false); $this->clearStartField(); if (self::$eventClassName) { $eventManager = Main\EventManager::getInstance(); if ($eventsList = $eventManager->findEventHandlers('sale', 'OnAfter'.self::$eventClassName.'FinalAction')) { $event = new Main\Event( 'sale', 'OnAfter'.self::$eventClassName.'FinalAction', array('ENTITY' => $this) ); $event->send(); } } return $result; } /** * Apply the result of the discounts to the order. * * @internal * * @param array $data * @return Result * @throws Main\ArgumentNullException */ public function applyDiscount(array $data) { if (!empty($data['BASKET_ITEMS']) && is_array($data['BASKET_ITEMS'])) { /** @var BasketBase $basket */ $basket = $this->getBasket(); $basketResult = $basket->applyDiscount($data['BASKET_ITEMS']); if (!$basketResult->isSuccess()) return $basketResult; unset($basketResult, $basket); $this->refreshOrderPrice(); } return new Result(); } /** * @param $value * @return Result * @throws Main\ArgumentException */ protected function setReasonMarked($value) { $result = new Result(); if (!empty($value)) { $orderReasonMarked = $this->getField('REASON_MARKED'); if (is_array($value)) { $newOrderReasonMarked = ''; foreach ($value as $err) { $newOrderReasonMarked .= (strval($newOrderReasonMarked) != '' ? "\n" : "") . $err; } } else { $newOrderReasonMarked = $value; } /** @var Result $r */ $r = $this->setField('REASON_MARKED', $orderReasonMarked. (strval($orderReasonMarked) != '' ? "\n" : ""). $newOrderReasonMarked); if (!$r->isSuccess()) { $result->addErrors($r->getErrors()); } } return $result; } /** * Reset the value of the order and delivery * * @internal * * @param array $select * @throws Main\ArgumentOutOfRangeException */ public function resetData($select = array('PRICE')) { if (in_array('PRICE', $select)) { $this->setFieldNoDemand('PRICE', 0); } if (in_array('PRICE_DELIVERY', $select)) { $this->setFieldNoDemand('PRICE_DELIVERY', 0); } } /** * @param $value * @param $oldValue * @return bool * @throws Main\ArgumentException * @throws Main\ArgumentNullException * @throws Main\ArgumentOutOfRangeException * @throws Main\NotImplementedException */ protected function isStatusChangedOnPay($value, $oldValue) { $registry = Registry::getInstance(static::getRegistryType()); /** @var OrderStatus $orderStatus */ $orderStatus = $registry->getOrderStatusClassName(); $allowPayStatus = $orderStatus::getAllowPayStatusList(); $disallowPayStatus = $orderStatus::getDisallowPayStatusList(); return !empty($disallowPayStatus) && in_array($oldValue, $disallowPayStatus) && !empty($allowPayStatus) && in_array($value, $allowPayStatus); } /** * Create order clone * * @return OrderBase * @throws Main\ArgumentException * @throws Main\NotImplementedException * @throws Main\SystemException */ public function createClone() { $cloneEntity = new \SplObjectStorage(); /** @var OrderBase $orderClone */ $orderClone = clone $this; $orderClone->isClone = true; /** @var Internals\Fields $fields */ if ($fields = $this->fields) { $orderClone->fields = $fields->createClone($cloneEntity); } /** @var Internals\Fields $calculatedFields */ if ($calculatedFields = $this->calculatedFields) { $orderClone->calculatedFields = $calculatedFields->createClone($cloneEntity); } if (!$cloneEntity->contains($this)) { $cloneEntity[$this] = $orderClone; } $this->cloneEntities($cloneEntity); return $orderClone; } /** * @param \SplObjectStorage $cloneEntity * @throws Main\ArgumentException * @throws Main\NotImplementedException * @throws Main\SystemException */ protected function cloneEntities(\SplObjectStorage $cloneEntity) { if (!$cloneEntity->contains($this)) { throw new Main\SystemException(); } $orderClone = $cloneEntity[$this]; /** @var BasketBase $basket */ if ($basket = $this->getBasket()) { $orderClone->basketCollection = $basket->createClone($cloneEntity); } /** @var PropertyValueCollectionBase $propertyCollection */ if ($propertyCollection = $this->getPropertyCollection()) { $orderClone->propertyCollection = $propertyCollection->createClone($cloneEntity); } if ($tax = $this->getTax()) { $orderClone->tax = $tax->createClone($cloneEntity); } if ($discount = $this->getDiscount()) { $orderClone->discount = $discount->createClone($cloneEntity); } } /** * @param array $data * @throws Main\NotImplementedException * @return Main\Entity\AddResult */ abstract protected function addInternal(array $data); /** * @param $primary * @param array $data * @throws Main\NotImplementedException * @return Main\Entity\UpdateResult */ protected static function updateInternal($primary, array $data) { throw new Main\NotImplementedException(); } /** * @param $primary * @throws Main\NotImplementedException * @return Main\Entity\DeleteResult */ protected static function deleteInternal($primary) { throw new Main\NotImplementedException(); } /** * Return user field id * * @return null */ public static function getUfId() { return null; } /** * @deprecated Use \Bitrix\Sale\OrderBase::getAvailableFields instead * * @return array */ public static function getSettableFields() { return static::getAvailableFields(); } }