Files
crm.clientright.ru/modules/SPCMLConnector/SalesOrderController.php
Fedor ac7467f0b4 Major CRM updates: AI Assistant, Court Status API, S3 integration improvements, and extensive file storage system
- Added comprehensive AI Assistant system (aiassist/ directory):
  * Vector search and embedding capabilities
  * Typebot proxy integration
  * Elastic search functionality
  * Message classification and chat history
  * MCP proxy for external integrations

- Implemented Court Status API (GetCourtStatus.php):
  * Real-time court document status checking
  * Integration with external court systems
  * Comprehensive error handling and logging

- Enhanced S3 integration:
  * Improved file backup system with metadata
  * Batch processing capabilities
  * Enhanced error logging and recovery
  * Copy operations with URL fixing

- Added Telegram contact creation API
- Improved error logging across all modules
- Enhanced callback system for AI responses
- Extensive backup file storage with timestamps
- Updated documentation and README files

- File storage improvements:
  * Thousands of backup files with proper metadata
  * Fix operations for broken file references
  * Project-specific backup and recovery systems
  * Comprehensive file integrity checking

Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
2025-10-16 11:17:21 +03:00

351 lines
13 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: SalesPlatform Ltd
* The Initial Developer of the Original Code is SalesPlatform Ltd.
* All Rights Reserved.
* If you have any questions or comments, please email: devel@salesplatform.ru
************************************************************************************/
require_once "modules/SPCMLConnector/OperationController.php";
require_once "modules/SPCMLConnector/ProductsController.php";
require_once "modules/SPCMLConnector/ServicesController.php";
require_once "modules/SPCMLConnector/AccountsController.php";
/**
* Describes create/update and xml upload operations by CmlSalesOrder inventory.
*/
class SalesOrderController extends OperationController {
private $productsController;
private $servicesController;
protected $accountController; //need acces in childs - to redefine account in order
/**
* CmlSalesorder object which need to be saved.
* @var CmlSalesOrder
*/
protected $cmlSalesOrder;
public function __construct($assignedUserName) {
parent::__construct($assignedUserName);
$this->productsController = new ProductsController($assignedUserName);
$this->servicesController = new ServicesController($assignedUserName);
$this->accountController = new AccountsController($assignedUserName);
}
/**
* Return reference of products module.
* @return int
*/
private function getProductsPrefix() {
$result = $this->describe("Products");
return $result['idPrefix'];
}
/**
* Generate REST description of inventories by $cmlSalesOrder
* @return array
*/
private function generateInventoriesRest() {
$inventoriesRest = array();
foreach($this->cmlSalesOrder->getProducts() as $cmlProduct) {
$productRest = $this->productsController->getSalesOrderInventoryRest($cmlProduct);
$inventoriesRest['LineItems'][] = $productRest;
}
foreach($this->cmlSalesOrder->getServices() as $cmlService) {
$serviceRest = $this->servicesController->getSalesOrderInventoryRest($cmlService);
$inventoriesRest['LineItems'][] = $serviceRest;
}
$inventoriesRest['productid'] = $this->getProductsPrefix(); //vtiger 6 need it param
return $inventoriesRest;
}
/**
* Generates REST description of account in order.
* @return array
*/
private function generateAccountRest() {
$cmlAccount = $this->cmlSalesOrder->getAccount();
return $this->accountController->getSalesOrderAccountRest($cmlAccount);
}
/**
* Return REST description of currency and tax type (individual)
* @return array
*/
private function generateTaxRest() {
$currencyCode = $this->cmlSalesOrder->getCurrency();
$currencyReference = $this->getCurrencyReference($currencyCode);
$restData = array();
$restData['currency_id'] = $currencyReference;
$restData['hdnTaxType'] = 'individual';
return $restData;
}
/**
* Add inventories REST to order
* @param array $order
* @param array $inventories
* @return array
*/
private function joinInventoriesToOrder($order, $inventories) {
return array_merge($order, $inventories);
}
/**
* Updates exists record from 1C information.
* @param cmlSalesOrder $cmlSalesOrder
* @param String $reference
*/
private function updateOrder($reference) {
$restData = $this->buildSalesOrderRest();
$this->update($restData, $reference);
}
/**
* Return reference on order specified to 1C.
* @param cmlSalesorder $cmlSalesOrder
*/
protected function getReference() {
$number = $this->cmlSalesOrder->getNumber();
$result = $this->query("select id from SalesOrder where salesorder_no = '$number';");
return $this->getFirstReference($result);
}
/**
* Return basic SalesOrder REST array, specified for controller type (here it 1C)
* @return array
*/
protected function getBasicRest() {
$restData['one_s_id'] = $this->cmlSalesOrder->getOneEsId();
return $restData;
}
/**
* Return REST description of sostatus and invoicestatus
* @return array
*/
protected function generateStatuses() {
$restData = array();
if($this->cmlSalesOrder->getPropValue("Номер оплаты по 1С") != null) {
$restData['invoicestatus'] = 'Paid';
} else {
$restData['invoicestatus'] = 'AutoCreated';
}
/* One Es generate values as strings true or false */
if($this->cmlSalesOrder->getPropValue("Проведен") === 'true') {
$restData['sostatus'] = 'Delivered';
} elseif($this->cmlSalesOrder->getPropValue("ПометкаУдаления") === 'true') {
$restData['sostatus'] = 'Cancelled';
} else {
$restData['sostatus'] = 'Created';
}
return $restData;
}
/**
* Return REST to save salesOrder by information from one es.
* @param cmlSalesorder $cmlSalesOrder
*/
protected function buildSalesOrderRest() {
$orderBasic = $this->getBasicRest();
$statuses = $this->generateStatuses();
$account = $this->generateAccountRest();
$taxes = $this->generateTaxRest();
$orederRest = array_merge($statuses, $account, $taxes, $orderBasic);
/* Add to order REST inventories to save, and return REST description */
$inventories = $this->generateInventoriesRest();
return $this->joinInventoriesToOrder($orederRest, $inventories);
}
/**
* Filter SalesOrders which will be uploaded.
* @param String $beginTime
* @return array
*/
protected function getSalesOrdersToUpload($beginTime) {
$salesOrdersResult = $this->query("select id from SalesOrder where modifiedtime > '$beginTime';");
$salesOrders = array();
foreach($salesOrdersResult as $resultLine) {
$salesOrders[] = $this->retrieve($resultLine['id']);
}
return $salesOrders;
}
/**
* Save SalesOrder by 1C information.
* @param CmlSalesOrder $cmlSalesOrder
*/
public function saveOrder($cmlSalesOrder) {
$this->cmlSalesOrder = $cmlSalesOrder;
$reference = $this->getReference();
/* Only update exists SalesOrder from 1C - never create new */
if($reference != null) {
$this->updateOrder($reference);
}
}
/**
* Return xml description of all orders, which modified after $beginTime.
* @param String $beginTime - date after which SalesOrder search. Need Mysql DateTime format.
*/
public function getXmlOrders($beginTime) {
if($beginTime == null) {
$beginTime = date("Y-m-d H:i:s", 0); //if no time - upload all salesOrders
}
$salesOrders = $this->getSalesOrdersToUpload($beginTime);
$commerceData = $this->getCommerceHeader();
foreach($salesOrders as $order) {
$this->addSalesOrder($commerceData, $order);
}
return $commerceData->asXML();
}
/**
* Add currency code to document by refernece.
* @param SimpleXmlElement $document
* @param array $salesOrderRest
* @return String
*/
private function addXmlCurrencyCode($document, $salesOrderRest) {
$currencyReference = $salesOrderRest['currency_id'];
$currencyCode = $this->getCurrencyCode($currencyReference);
$document->addChild("Валюта", $currencyCode);
}
/**
* Add to order account information. Billing and shipping addresses add from
* salesOrder REST data - because in account can be empty fileds.
* @param SimpleXmlElement $document
* @param array $salesOrderRest
*/
protected function addXmlAccount($document, $salesOrderRest) {
$accountReference = $salesOrderRest['account_id'];
$account = $this->accountController->getXmlBaseAccount($accountReference);
$accounts = $document->addChild("Контрагенты");
$this->appendXmlElement($accounts, $account);
}
/**
*
* @param SimpleXmlElement $document
* @param array $salesOrderRest
*/
private function addXmlOrderInventories($document, $salesOrderRest) {
$inventoriesContainer = $document->addChild("Товары");
foreach($salesOrderRest['LineItems'] as $inventory) {
$this->addXmlInventory($inventoriesContainer, $inventory);
}
}
/**
* Add inventory to inventories tag container.
* @param SimpleXmlElement $inventoriesContainer
* @param array $inventory
*/
private function addXmlInventory($inventoriesContainer, $inventory) {
$inventoryId = $this->trimReference($inventory['productid']);
$inventoryXml = $this->productsController->getCatalogXmlInventoryById($inventoryId);
if($inventoryXml == null) {
$inventoryXml = $this->servicesController->getCatalogXmlInventoryById($inventoryId);
}
/* In CRM may be deleted inventories from CRM, but not deleted from order. */
if($inventoryXml == null) {
return;
}
/* Common fields of products and services on SalesOrder */
$inventoryXml->addChild("ЦенаЗаЕдиницу", $inventory['listprice']);
$inventoryXml->addChild("Количество", $inventory['quantity']);
$inventoryXml->addChild("Сумма", $inventory['quantity'] * $inventory['listprice']);
$this->appendXmlElement($inventoriesContainer, $inventoryXml);
}
/**
* Add order identificator to order.
* @param SimpleXmlElement $order
* @param array $salesOrderRest
*/
protected function addXmlOrderIdentificator($order, $salesOrderRest) {
if($salesOrderRest['one_s_id']!=null){
$order->addChild("Ид", $salesOrderRest['one_s_id']);
} else {
$order->addChild("Ид", $salesOrderRest['salesorder_no']);
}
}
/**
* Add props to document by information from REST description.
* @param SimpleXmlElement $document
* @param array $salesOrderRest
*/
protected function addOrderProps($document, $salesOrderRest) {
$documentProps = $document->addChild("ЗначенияРеквизитов");
$documentProp = $documentProps->addChild("ЗначениеРеквизита");
$documentProp->addChild("Наименование", "НомерНаСайте");
$documentProp->addChild("Значение", $salesOrderRest['salesorder_no']);
$documentProp = $documentProps->addChild("ЗначениеРеквизита");
$documentProp->addChild("Наименование", "ДатаНаСайте");
$documentProp->addChild("Значение", strstr($salesOrderRest['createdtime'], " ", true));
$documentProp = $documentProps->addChild("ЗначениеРеквизита");
$documentProp->addChild("Наименование", "Статус заказа");
$documentProp->addChild("Значение", $salesOrderRest['sostatus']);
}
/**
* Add to documrnt it number, specified for order - from one es or from website.
* @param SimpleXmlElement $document
* @param array $salesOrderRest
*/
protected function addXmlOrderNumber($document, $salesOrderRest) {
$document->addChild("Номер",$salesOrderRest['salesorder_no']);
}
/**
* Add to xml order description base order information.
* @param SimpleXmlElement $document
* @param array $salesOrderRest
*/
private function addXmlOrderHeader($document, $salesOrderRest) {
$this->addXmlOrderNumber($document, $salesOrderRest);
$document->addChild("Дата", strstr($salesOrderRest['createdtime'], " ", true));
$document->addChild("ХозОперация", "Заказ товара");
$document->addChild("Роль", "Продавец");
$document->addChild("Время", substr($salesOrderRest['createdtime'],
strpos($salesOrderRest['createdtime'], " ") + 1) );
}
/**
* Add to commerceData salesOrder.
* @param SimpleXmlElement $commerceData
* @param array $salesOrderRest
*/
private function addSalesOrder($commerceData, $salesOrderRest) {
$document = $commerceData->addChild("Документ");
$this->addXmlOrderHeader($document, $salesOrderRest);
$this->addXmlOrderIdentificator($document, $salesOrderRest);
$this->addXmlCurrencyCode($document, $salesOrderRest);
$this->addXmlAccount($document, $salesOrderRest);
$this->addXmlOrderInventories($document, $salesOrderRest);
$this->addOrderProps($document, $salesOrderRest);
}
}