Your IP : 18.223.213.54


Current Path : /var/www/axolotl/data/www/nn.axolotls.ru/bitrix/modules/crm/lib/binding/
Upload File :
Current File : /var/www/axolotl/data/www/nn.axolotls.ru/bitrix/modules/crm/lib/binding/ordercontactcompany.php

<?php
/**
 * Bitrix Framework
 * @package bitrix
 * @subpackage crm
 * @copyright 2001-2018 Bitrix
 */
namespace Bitrix\Crm\Binding;

use Bitrix\Main;
use Bitrix\Main\Entity;
use Bitrix\Crm\Order;

/**
 * Class OrderContactCompanyTable
 * @package Bitrix\Crm\Binding
 */
class OrderContactCompanyTable extends Entity\DataManager
{
	/**
	 * Get table name.
	 * @return string
	 */
	public static function getTableName()
	{
		return 'b_crm_order_contact_company';
	}
	/**
	 * Get table fields map.
	 * @return array
	 */
	public static function getMap()
	{
		return array(
			'ID' => array(
				'primary' => true,
				'data_type' => 'integer'
			),
			'ORDER_ID' => array(
				'data_type' => 'integer'
			),
			'ORDER' => array(
				'data_type' => '\Bitrix\Sale\Order',
				'reference' => array(
					'=this.ORDER_ID' => 'ref.ID'
				)
			),
			'ENTITY_ID' => array(
				'data_type' => 'integer'
			),
			'ENTITY_TYPE_ID' => array(
				'data_type' => 'integer'
			),
			'SORT' => array(
				'data_type' => 'integer',
				'default_value' => 0
			),
			'ROLE_ID' => array(
				'data_type' => 'integer',
				'default_value' => 0
			),
			'IS_PRIMARY' => array(
				'data_type' => 'boolean',
				'values' => array('N', 'Y'),
				'default_value' => 'N'
			)
		);
	}
	/**
	 * Execute UPSERT operation.
	 * @param array $data Field data.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 */
	public static function upsert(array $data)
	{
		$orderId = isset($data['ORDER_ID']) ? (int)$data['ORDER_ID'] : 0;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must contains ORDER_ID field.', 'data');
		}

		$contactID = isset($data['ENTITY_ID']) ? (int)$data['ENTITY_ID'] : 0;
		if($contactID <= 0)
		{
			throw new Main\ArgumentException('Must contains ENTITY_ID field.', 'data');
		}

		$sort = isset($data['SORT']) ? (int)$data['SORT'] : 0;
		$roleID = isset($data['ROLE_ID']) ? (int)$data['ROLE_ID'] : 0;
		$primary = isset($data['IS_PRIMARY']) && strtoupper($data['IS_PRIMARY']) === 'Y' ? 'Y' : 'N';

		$connection = Main\Application::getConnection();
		$queries = $connection->getSqlHelper()->prepareMerge(
			'b_crm_order_contact',
			array('ORDER_ID', 'ENTITY_ID'),
			array('ORDER_ID' => $orderId, 'ENTITY_ID' => $contactID, 'SORT' => $sort, 'ROLE_ID' => $roleID, 'IS_PRIMARY' => $primary),
			array('SORT' => $sort, 'ROLE_ID' => $roleID, 'IS_PRIMARY' => $primary)
		);

		foreach($queries as $query)
		{
			$connection->queryExecute($query);
		}
	}
	/**
	 * Get order IDs are bound to specified contact.
	 * @param int $contactID Contact ID.
	 * @return array
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 */
	public static function getContactOrderIDs($contactID)
	{
		$contactID = (int)$contactID;
		if($contactID <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'contactID');
		}

		$dbResult =  Main\Application::getConnection()->query(
			/** @lang text*/
			"SELECT ORDER_ID FROM b_crm_order_contact_company WHERE ENTITY_ID = {$contactID}"
		);

		$results = array();
		while($ary = $dbResult->fetch())
		{
			$results[] = (int)$ary['ORDER_ID'];
		}
		return $results;
	}

	/**
	 * Get contact IDs are bound to specified order.
	 * @param int $orderId order ID.
	 * @return array
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 */
	public static function getOrderContactIDs($orderId)
	{
		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$dbResult = Main\Application::getConnection()->query(
			/** @lang text*/
			"SELECT ENTITY_ID FROM b_crm_order_contact_company WHERE ORDER_ID = {$orderId} ORDER BY SORT ASC"
		);

		$results = array();
		while($ary = $dbResult->fetch())
		{
			$results[] = (int)$ary['ENTITY_ID'];
		}
		return $results;
	}

	/**
	 * Get order's bindings.
	 * @param int $orderId Order ID.
	 * @return array
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 */
	public static function getOrderBindings($orderId)
	{
		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'order');
		}

		$dbResult = Main\Application::getConnection()->query(
			/** @lang text*/
			"SELECT ENTITY_ID, SORT, ROLE_ID, IS_PRIMARY FROM b_crm_order_contact_company WHERE ORDER_ID = ".$orderId." AND ENTITY_TYPE_ID = ".\CCrmOwnerType::Contact." ORDER BY SORT"
		);

		$results = array();
		while($ary = $dbResult->fetch())
		{
			$results[] = array(
				'CONTACT_ID' => (int)$ary['ENTITY_ID'],
				'SORT' => (int)$ary['SORT'],
				'ROLE_ID' => (int)$ary['ROLE_ID'],
				'IS_PRIMARY' => $ary['IS_PRIMARY']
			);
		}
		return $results;
	}

	/**
	 * Get order's binding count.
	 * @param int $orderId order ID.
	 * @return int
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 */
	public static function getOrderBindingCount($orderId)
	{
		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$dbResult = Main\Application::getConnection()->query(
			/** @lang text*/
			"SELECT COUNT(*) CNT FROM b_crm_order_contact_company WHERE ORDER_ID = {$orderId}"
		);

		$ary = $dbResult->fetch();
		return is_array($ary) ? (int)$ary['CNT'] : 0;
	}

	/**
	 * Check if order has contacts.
	 * @param int $orderId Order ID.
	 * @return bool
	 * @throws Main\ArgumentException
	 * @throws Main\ObjectPropertyException
	 * @throws Main\SystemException
	 */
	public static function hasContacts($orderId)
	{
		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$result = self::getList(
			array(
				'select' => array('ORDER_ID'),
				'filter' => array('=ORDER_ID' => $orderId),
				'limit' => 1
			)
		);

		return is_array($result->fetch());
	}

	/**
	 * Bind order to contacts are specified by ID.
	 * @param int $orderId Order ID.
	 * @param array $contactIDs Array of contact IDs.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\ArgumentOutOfRangeException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\NotSupportedException
	 * @throws Main\SystemException
	 */
	public static function bindContactIDs($orderId, array $contactIDs)
	{
		$bindings = EntityBinding::prepareEntityBindings(\CCrmOwnerType::Contact, $contactIDs);
		$qty = count($bindings);
		if($qty > 0)
		{
			for($i = 0; $i < $qty; $i++)
			{
				if($i === 0)
				{
					$bindings[$i]['IS_PRIMARY'] = 'Y';
				}
				$bindings[$i]['SORT'] = 10 * ($i + 1);
			}
			self::bindContacts($orderId, $bindings);
		}
	}

	/**
	 * Bind order to contacts.
	 * @param int $orderId order id.
	 * @param array $bindings Array of contact bindings.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\SystemException
	 * @throws Main\LoaderException
	 */
	public static function bindContacts($orderId, array $bindings)
	{
		if(!Main\Loader::includeModule('sale'))
			throw new Main\SystemException('Can\'t include module "sale"');

		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$qty = count($bindings);
		if($qty === 0)
		{
			return;
		}

		$processed = 0;
		for($i = 0; $i < $qty; $i++)
		{
			$binding = $bindings[$i];

			$contactID = isset($binding['ENTITY_ID']) ? (int)$binding['ENTITY_ID'] : 0;
			if($contactID <= 0)
			{
				continue;
			}

			self::upsert(
				array(
					'ORDER_ID' => $orderId,
					'ENTITY_ID' => $contactID,
					'SORT' => isset($binding['SORT']) ? (int)$binding['SORT'] : (10 * ($i + 1)),
					'ROLE_ID' => isset($binding['ROLE_ID']) ? (int)$binding['ROLE_ID'] : EntityBinding::ROLE_UNDEFINED,
					'IS_PRIMARY' => isset($binding['IS_PRIMARY']) ? $binding['IS_PRIMARY'] : ''
				)
			);
			$processed++;
		}

		if($processed > 0)
		{
			Main\Application::getConnection()->queryExecute(
				/** @lang text*/
				"UPDATE b_sale_order SET ENTITY_ID =
				(SELECT MIN(ENTITY_ID) FROM b_crm_order_contact_company WHERE IS_PRIMARY = 'Y' AND ORDER_ID = {$orderId})
				WHERE ID = {$orderId}"
			);
		}
	}

	/**
	 * Unbind specified order from specified contacts.
	 * @param int $orderId order id.
	 * @param array $contactIDs Array of contact IDs.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\SystemException
	 */
	public static function unbindContactIDs($orderId, array $contactIDs)
	{
		if(!Main\Loader::includeModule('sale'))
			throw new Main\SystemException('Can\'t include module "sale"');

		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$contactIDs = array_filter($contactIDs);
		if(empty($contactIDs))
		{
			return;
		}

		$connection = Main\Application::getConnection();

		$values = implode(',', $contactIDs);
		$connection->queryExecute(
			/** @lang text */
			"DELETE FROM b_crm_order_contact_company WHERE ORDER_ID = {$orderId} AND ENTITY_ID IN({$values})"
		);

		$connection->queryExecute(
			/** @lang text*/
			"UPDATE b_sale_order SET ENTITY_ID =
			(SELECT MIN(ENTITY_ID) FROM b_crm_order_contact_company WHERE IS_PRIMARY = 'Y' AND ORDER_ID = {$orderId})
			WHERE ID = {$orderId}"
		);
	}

	/**
	 * Unbind specified order from specified contacts.
	 * @param int $orderId Order ID.
	 * @param array $bindings Array of bindings.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\ArgumentOutOfRangeException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\NotSupportedException
	 * @throws Main\SystemException
	 */
	public static function unbindContacts($orderId, array $bindings)
	{
		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		self::unbindContactIDs($orderId, EntityBinding::prepareEntityIDs(\CCrmOwnerType::Contact, $bindings));
	}

	/**
	 * Unbind specified order from all contacts.
	 * @param int $orderId Order ID.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\SystemException
	 */
	public static function unbindAllContacts($orderId)
	{
		if(!Main\Loader::includeModule('sale'))
			throw new Main\SystemException('Can\'t include module "sale"');

		$orderId = (int)$orderId;
		if($orderId <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'orderId');
		}

		$connection = Main\Application::getConnection();
		$connection->queryExecute(
			/** @lang text */
			"DELETE FROM b_crm_order_contact_company WHERE ORDER_ID = {$orderId}"
		);
		$connection->queryExecute(
			/** @lang text */
			"UPDATE b_sale_order SET ENTITY_ID = NULL WHERE ID = {$orderId}"
		);
	}

	/**
	 * Unbind specified contact from all orders.
	 * @param int $contactID Contact ID.
	 * @return void
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\SystemException
	 */
	public static function unbindAllOrders($contactID)
	{
		if(!Main\Loader::includeModule('sale'))
			throw new Main\SystemException('Can\'t include module "sale"');

		$contactID = (int)$contactID;
		if($contactID <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'contactID');
		}

		$connection = Main\Application::getConnection();
		$connection->queryExecute(
		/** @lang text */
			"DELETE FROM b_crm_order_contact_company WHERE ENTITY_ID = {$contactID}"
		);
		$connection->queryExecute(
		/** @lang text */
			"UPDATE b_sale_order SET ENTITY_ID =
			(SELECT MIN(ENTITY_ID) FROM b_crm_order_contact_company t WHERE t.ORDER_ID = b_sale_order.ID)
			WHERE ENTITY_ID = {$contactID}"
		);
	}

	/**
	 * Prepage SQL join filter condition for specified entity.
	 * @param int $entityTypeID Entity type ID for filter.
	 * @param int $entityID Entity ID for filter.
	 * @param string $tableAlias Alias of primary table.
	 * @return string
	 * @throws Main\ArgumentException
	 * @throws Main\ArgumentOutOfRangeException
	 * @throws Main\NotSupportedException
	 */
	public static function prepareFilterJoinSql($entityTypeID, $entityID, $tableAlias)
	{
		if(!is_int($entityTypeID))
		{
			$entityTypeID = (int)$entityTypeID;
		}

		if(!\CCrmOwnerType::IsDefined($entityTypeID))
		{
			throw new Main\ArgumentOutOfRangeException('entityTypeID',
				\CCrmOwnerType::FirstOwnerType,
				\CCrmOwnerType::LastOwnerType
			);
		}

		if($entityTypeID !== \CCrmOwnerType::Contact && $entityTypeID !== \CCrmOwnerType::Order)
		{
			$entityTypeName = \CCrmOwnerType::ResolveName($entityTypeID);
			throw new Main\NotSupportedException("Entity type: '{$entityTypeName}' is not supported in current context");
		}

		$entityIDs = is_array($entityID) ? $entityID : array($entityID);
		$effectiveIDs = array();
		foreach($entityIDs as $ID)
		{
			$ID = (int)$ID;
			if($ID > 0)
			{
				$effectiveIDs[] = $ID;
			}
		}

		$qty = count($effectiveIDs);
		if($qty > 1)
		{
			$slug = implode(',', $effectiveIDs);
			if($entityTypeID === \CCrmOwnerType::Contact)
			{
				return "INNER JOIN b_crm_order_contact_company QC ON QC.ENTITY_ID IN({$slug}) AND QC.ORDER_ID = {$tableAlias}.ID";
			}
			else//if($entityTypeID === \CCrmOwnerType::Order)
			{
				return "INNER JOIN b_crm_order_contact_company QC ON QC.ORDER_ID IN({$slug}) AND QC.ENTITY_ID = {$tableAlias}.ID";
			}
		}
		elseif($qty === 1)
		{
			if($entityTypeID === \CCrmOwnerType::Contact)
			{
				return "INNER JOIN b_crm_order_contact_company QC ON QC.ENTITY_ID = {$effectiveIDs[0]} AND QC.ORDER_ID = {$tableAlias}.ID";
			}
			else//if($entityTypeID === \CCrmOwnerType::Order)
			{
				return "INNER JOIN b_crm_order_contact_company QC ON QC.ORDER_ID = {$effectiveIDs[0]} AND QC.ENTITY_ID = {$tableAlias}.ID";
			}
		}
		return "";
	}

	/**
	 * Unbind all orders from seed contact and bind to target contact
	 * @param int $seedContactID Seed contact ID.
	 * @param int $targContactID Target contact ID.
	 * @throws Main\ArgumentException
	 * @throws Main\Db\SqlQueryException
	 * @throws Main\LoaderException
	 * @throws Main\SystemException
	 */

	public static function rebindAllOrders($seedContactID, $targContactID)
	{
		$seedContactID = (int)$seedContactID;
		if($seedContactID <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'seedContactID');
		}

		$targContactID = (int)$targContactID;
		if($targContactID <= 0)
		{
			throw new Main\ArgumentException('Must be greater than zero', 'targContactID');
		}

		if($seedContactID === $targContactID)
		{
			return;
		}

		$connection = Main\Application::getConnection();
		$dbResult = $connection->query(
		/** @lang text */
			"SELECT ORDER_ID FROM b_crm_order_contact_company WHERE ENTITY_ID = {$seedContactID}"
		);

		while($fields = $dbResult->fetch())
		{
			$orderId = (int)$fields['ORDER_ID'];
			$bindings = self::getOrderBindings($orderId);
			$seedIndex = $targIndex = -1;
			for($i = 0, $l = count($bindings); $i < $l; $i++)
			{
				$binding = $bindings[$i];
				$contactID = (int)$binding['ENTITY_ID'];
				if($contactID === $seedContactID)
				{
					$seedIndex = $i;
				}
				elseif($contactID === $targContactID)
				{
					$targIndex = $i;
				}

				if($seedIndex >= 0 && $targIndex >= 0)
				{
					break;
				}
			}

			$seedBinding = $seedIndex >= 0 ? $bindings[$seedIndex] : null;
			$targBinding = $targIndex >= 0 ? $bindings[$targIndex] : null;

			if(!is_array($seedBinding))
			{
				continue;
			}

			self::unbindContactIDs($orderId, array($seedContactID));

			$isPrimary = isset($seedBinding['IS_PRIMARY']) && $seedBinding['IS_PRIMARY'] === 'Y';
			if(!is_array($targBinding))
			{
				$seedBinding['ENTITY_ID'] = $targContactID;
				self::bindContacts($orderId, array($seedBinding));
			}
			elseif($isPrimary)
			{
				$targBinding['IS_PRIMARY'] = 'Y';
				self::bindContacts($orderId, array($targBinding));
			}
		}
	}

	/**
	 * Get orders by entities.
	 * <p>$entities:
	 * [
	 *    ['TYPE_ID' => \CCrmOwnerType::Contact, 'ID' => 123],
	 *    ['TYPE_ID' => \CCrmOwnerType::Company, 'ID' => 321],
	 * ]
	 * </p>
	 *
	 * @param array $entities Entity list with type ID and entity ID.
	 * @param bool $isPrimary Return only primary results.
	 * @return int[]
	 */
	public static function getOrdersByEntities(array $entities, $isPrimary = true)
	{
		$list = [];
		foreach ($entities as $entity)
		{
			$typeId = isset($entity['TYPE_ID']) ? (int) $entity['TYPE_ID'] : null;
			$id = isset($entity['ID']) ? (int) $entity['ID'] : null;

			if (!$typeId || !$id)
			{
				continue;
			}

			if (!isset($list[$typeId]))
			{
				$list[$typeId] = [];
			}
			$list[$typeId][] = $id;
		}

		if (empty($list))
		{
			return [];
		}

		$result = [];

		$filter = [
			'=ENTITY_TYPE_ID' => array_keys($list),
			'=ENTITY_ID' => array_unique(array_reduce(array_values($list), 'array_merge', [])),
			'=ORDER.STATUS_ID' => Order\OrderStatus::getSemanticProcessStatuses(),
		];
		if ($isPrimary)
		{
			$filter['=IS_PRIMARY'] = 'Y';
		}
		$orders = static::getList([
			'select' => ['ORDER_ID', 'ENTITY_TYPE_ID', 'ENTITY_ID'],
			'filter' => $filter
		])->fetchAll();
		foreach ($orders as $item)
		{
			$typeId = (int) $item['ENTITY_TYPE_ID'];
			$id = (int) $item['ENTITY_ID'];

			if (!in_array($id, $list[$typeId]))
			{
				continue;
			}

			$result[] = (int) $item['ORDER_ID'];
		}

		return $result;
	}
}