Version: current

      1 <?php
      2
      3 class Orders1CExchange_Exporter extends Base1CExchanger {
      4     //Unpaid,Paid,Processing,Complete
      5     static $statuses1C = array(
      6         'Unpaid' => 'Новый',
      7         'Query' => 'В работе',
      8         'Paid' => 'Оплачен',
      9         'Processing' => 'В обработке',
     10         'Sent' => 'Отправлен',
     11         'Complete' => 'Завершен',
     12         'AdminCancelled' => 'Отменен магазином',
     13         'MemberCancelled' => 'Отменен пользователем',
     14     );
     15
     16     function exportOrders($log) {
     17         $log->addStatus('process', _t('Orders1CExchangeExporter.OrdersExportStarted', 'Старт экспорта заказов'));
     18         $log->addLog(_t('Orders1CExchangeExporter.OrdersExportStarted', 'Старт экспорта заказов'));
     19
     20         $document = array();
     21         $statusesExportFrom = SiteConfig::current_site_config()->StatusesToExport();
     22         $orders = DataObject::get('Order', 'IsExported = 0 AND Status IN(' . implode(', ', $statusesExportFrom) . ')', 'ID DESC');
     23         if ($orders) {
     24             $sc = SiteConfig::current_site_config();
     25             $document_counter = 0;
     26             foreach ($orders as $order) {
     27                 $date = date('Y-m-d', strtotime($order->Created));
     28                 $time = date('H:i:s', strtotime($order->Created));
     29
     30                 $document['Документ' . $document_counter] = array(
     31                     'Ид'          => $order->ID,
     32                     'Номер'       => $order->ID,
     33                     'Дата'        => $date,
     34                     'Время'       => $time,
     35                     'Валюта'      => $sc->CatalogCurrency,
     36                     'Курс'        => 1,
     37                     'ХозОперация' => 'Заказ товара',
     38                     'Роль'        => 'Продавец',
     39                     'Сумма'       => $order->GrandTotal,
     40                     'Комментарий' => $order->ClientNotes
     41                 );
     42                 // обратно скидка приходит не по всему заказау а по каждому товару отдельно (1С вычисляет по общей сикдке скидку по каждому товару)
     43                 if ($order->Discount) {
     44                     $document['Документ' . $document_counter]['Скидки']['Скидка'] = array(
     45                         'Наименование' => 'Скидка',
     46                         'Сумма' => $order->Discount,
     47                         'УчтеноВСумме' => 1,
     48                     );
     49                 }
     50                 $document['Документ' . $document_counter]['Контрагенты']['Контрагент'] = array(
     51                     'Ид'                 => $order->MemberID . '#' . $order->Email, // !!! непонятно, что указывать - должен быть уникальный ID контрагента
     52                     'Наименование'          => trim($order->ClientName), // по имени - в Order есть только ClientName, но Order может быть расширен (добавлена Фамилия, Отчество)
     53                     'Роль'               => 'Покупатель',
     54                     'ПолноеНаименование'  => trim($order->ClientName), // по имени ...
     55                     'Имя'                      => $order->ClientName,// по имени ...
     56
     57                     /*  Контакты
     58                         Коды:
     59                             Телефон внутренний
     60                             Телефон рабочий
     61                             Телефон мобильный
     62                             Телефон домашний
     63                             Пейджер
     64                             Факс
     65                             Почта
     66                             ICQ
     67                             ВебСайт
     68                             Координаты на карте
     69                             Прочее
     70                     */
     71                     'Контакты' => array( // тип КонтактТип
     72                         'Контакт1' => array(
     73                             'Тип' => 'ТелефонРабочий'
     74                             ,'Значение' => $order->Phone
     75                         )
     76                         ,'Контакт2'  => array(
     77                              'Тип' => 'Почта'
     78                             ,'Значение' => $order->Email
     79                         )
     80                     )
     81                 );
     82                 /* !!!!нету у Order поля LastName
     83                 if ($order->LastName) {
     84                     $document['Документ' . $document_counter]['Контрагенты']['Контрагент']['Фамилия'] = $order->LastName;
     85                 }
     86                 */
     87
     88                 $address = array();
     89                 if ($order->Address)
     90                     $address[] = $order->Address;
     91                 if ($order->City)
     92                     $address[] = $order->City;
     93                 if ($order->PostalCode)
     94                     $address[] = $order->PostalCode;
     95                 if ($order->Country)
     96                     $address[] = $order->Country;
     97                 if (count($address)) {
     98                     // в примере АдресРегистрации и несколько АдресноеПоле с "Почтовый индекс", "Улица" и т.д. (тип АдресТип)
     99                     $document['Документ' . $document_counter]['Контрагенты']['Контрагент']['Адрес'] = array(
    100                         'Представление'    => implode(', ', $address)
    101                     );
    102                 }
    103
    104                 // Товары
    105                 $products = $order->Items();
    106                 $product_counter = 0;
    107                 foreach ($products as $product) {
    108                     if (!$product->getProduct()) {
    109                         continue;
    110                     }
    111                     $id = $product->ImportID;
    112                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter] = array(
    113                         'Ид'             => $id,
    114                         'ИдКаталога'     => $product->getProduct()->Parent()->ImportID,
    115                         'Артикул'      => $product->ImportID, // может SKU
    116                         'Наименование'   => $product->Title,
    117                         'БазоваяЕдиница' => 'шт', // должно быть <БазоваяЕдиница Код="796" НаименованиеПолное="Штука" МеждународноеСокращение="PCE">шт</БазоваяЕдиница>
    118                         'ЦенаЗаЕдиницу'  => $product->Price,
    119                         'Количество'     => $product->Quantity,
    120                         'Сумма'          => $product->TotalPrice,
    121                     );
    122                     // добавить 'БазоваяЕдиница' - Имя базовой единицы измерения товара по ОКЕИ (вроде как обязательно)
    123
    124                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита0']= array(
    125                         'Наименование' => 'ВидНоменклатуры',
    126                         'Значение'=> 'Товар',
    127                     );
    128                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита1']= array(
    129                         'Наименование' => 'ТипНоменклатуры',
    130                         'Значение'=> 'Товар',
    131                     );
    132                     $product_counter++;
    133                 }
    134
    135                 if ($product_counter == 0) {
    136                     unset($document['Документ' . $document_counter]);
    137                     continue;
    138                 }
    139
    140                 //Доставка
    141                 //  Доставка выводится как отдельный товар с Ид ORDER_DELIVERY
    142                 if ($order->ShippingTotal) {
    143                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter] = array(
    144                          'Ид'         => 'ORDER_DELIVERY'
    145                         ,'Наименование' => 'Доставка заказа'
    146                         ,'ЦенаЗаЕдиницу'=> $order->ShippingTotal
    147                         ,'Количество' => 1
    148                         ,'Сумма'       => $order->ShippingTotal
    149                     );
    150                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита0']= array(
    151                         'Наименование' => 'ВидНоменклатуры',
    152                         'Значение'=> 'Услуга',
    153                     );
    154                     $document['Документ' . $document_counter]['Товары']['Товар' . $product_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита1'] = array(
    155                         'Наименование' => 'ТипНоменклатуры',
    156                         'Значение'=> 'Услуга',
    157                     );
    158                 }
    159
    160                 //Статус
    161                 $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита0'] = array(
    162                     'Наименование' => 'Статус заказа',
    163                     'Значение'=> self::$statuses1C[$order->Status],
    164                 );
    165
    166                 //Метод оплаты
    167                 if ($order->hasMethod('PaymentType')) {
    168                     $method = $order->PaymentType();
    169                     if ($method) {
    170                         $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита1'] = array(
    171                             'Наименование' => 'Метод оплаты',
    172                             'Значение'=> $method->Title,
    173                         );
    174                     }
    175                 }
    176
    177                 //Способ доставки
    178                 // !! Пока под вопросом !!!
    179                 if ($order->hasMethod('ShippingMethod')) {
    180                     $method = $order->ShippingMethod();
    181                     if ($method) {
    182                         $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита2'] = array(
    183                             'Наименование' => 'Способ доставки',
    184                             'Значение'=> $method->Name,
    185                         );
    186                     }
    187                 }
    188
    189                 $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита3'] = array(
    190                     'Наименование' => 'Заказ оплачен',
    191                     'Значение'=> (in_array($order->Status, array('Paid','Processing', 'Sent','Complete')) ? 'true' : 'false'),
    192                 );
    193
    194                 $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита4'] = array(
    195                     'Наименование' => 'Отменен',
    196                     'Значение'=> (in_array($order->Status, array('AdminCancelled','MemberCancelled')) ? 'true' : 'false'),
    197                 );
    198
    199                 $document['Документ' . $document_counter]['ЗначенияРеквизитов']['ЗначениеРеквизита5']= array(
    200                     'Наименование' => 'Финальный статус',
    201                     'Значение'=> 'false', // пока всегда false
    202                 );
    203                 $document_counter++;
    204             }
    205         }
    206
    207         $root = '<?xml version="1.0" encoding="utf-8"?><КоммерческаяИнформация ВерсияСхемы="2.04" ДатаФормирования="' . date('Y-m-d', time()) . '" />';
    208         if ($document) {
    209             $log->addLog(sprintf(_t('Orders1CExchangeExporter.ExportedOrdersCount', 'Экспортировано %d заказов'), $document_counter));
    210             $xml = $this->array_to_xml($document, new SimpleXMLElement($root));
    211             file_put_contents(ASSETS_PATH . '/export_orders.xml', $xml->asXML());
    212             return $xml->asXML();
    213         }
    214         $log->addLog(_t('Orders1CExchangeExporter.NoExportedOrders', 'Нет заказов для экспорта'));
    215         return $root;
    216     }
    217
    218     function array_to_xml($data, &$xml) {
    219         foreach($data as $key => $value) {
    220             if (is_array($value)) {
    221                 if (!is_numeric($key)) {
    222                     $subnode = $xml->addChild(preg_replace('/\d/', '', $key));
    223                     $this->array_to_xml($value, $subnode);
    224                 }
    225             }
    226             else {
    227                 $xml->addChild($key, $value);
    228             }
    229         }
    230         return $xml;
    231     }
    232
    233     function setOrdersExported($log) {
    234         $log->addLog(_t('Orders1CExchangeExporter.SetOrdersExported', 'Подтверждение экспорта заказов'));
    235         $statusesExportFrom = SiteConfig::current_site_config()->StatusesToExport();
    236         $orders = DataObject::get('Order', 'IsExported = 0 AND Status IN(' . implode(', ', $statusesExportFrom) . ')');
    237         if ($orders) {
    238             foreach($orders as $order) {
    239                 //$order->IsExported = 1;
    240                 //$order->Update1C = 1;
    241                 //$order->write();
    242             }
    243         }
    244     }
    245
    246     function importOrders($filePath, $log) {
    247         $log->addStatus('process', _t('Orders1CExchangeExporter.OrdersImportStarted', 'Импорт заказов началася'));
    248         $log->addLog(_t('Orders1CExchangeExporter.OrdersImportStarted', 'Импорт заказов началася'));
    249
    250         $file = simplexml_load_file($filePath);
    251         $ordersCount = 0;
    252         foreach($file->Документ as $orderData) {
    253             $order = DataObject::get_by_id('Order', (int)$orderData->Номер);
    254             if (!$order || !$order->exists()) {
    255                 $log->addLog(sprintf(_t('Orders1CExchangeExporter.BadOrder', 'Заказ с Номер %s отсутствует на сайте или в нем нет элементов'), (string)$orderData->Номер), 'warning');
    256                 continue;
    257             }
    258             // проверим товары - может что добавили или удалили
    259             $productsID = $order->Items()->map('LinkedID', 'ID');
    260             $badOrder = false;
    261             foreach($orderData->Товары->Товар as $productData) {
    262                 if ($productData->Наименование == 'Доставка заказа') {
    263                     // !!! Все равно перетрется в ShippingOrderDecorator::onBeforeWrite() !!!
    264                     // !!!! ПОКА НЕРЕАЛИЗОВАНО !!!!
    265                     $order->ShippingTotal = (float)$productData->Сумма;
    266                     continue; // !!! доставку пока пропускаем, надо решить, чего с ней делать !!!
    267                 }
    268                 if ($product = DataObject::get_one('Product', "ImportID = '{$productData->Ид}'")) {
    269                     if (!isset($productsID[$product->ID])) {
    270                         $newItem = new OrderItem();
    271                         $newItem->Title = $product->Title;
    272                         $newItem->ItemPrice = (float)$productData->ЦенаЗаЕдиницу;
    273                         $newItem->Quantity = (int)$productData->Количество;
    274                         $newItem->OrderID = $order->ID;
    275                         $newItem->LinkedID = $product->ID;
    276                         $newItem->write();
    277                     } else {
    278                         $item = $order->Items()->find('ID', $productsID[$product->ID]);
    279                         unset($productsID[$product->ID]);
    280                         if ($item->ItemPrice != $productData->ЦенаЗаЕдиницу) {
    281                             $item->ItemPrice = (float)$productData->ЦенаЗаЕдиницу;
    282                         }
    283                         if ($item->Quantity != $productData->Количество) {
    284                             $item->Quantity = (int)$productData->Количество;
    285                         }
    286                         $item->write();
    287                     }
    288                 } else {
    289                     $log->addLog(sprintf(_t('Orders1CExchangeExporter.NoProduct', 'Продукт с ИД %s отсутствует на сайте'), (string)$productData->Ид ." Заказ: {$order->ID}"), 'warning');
    290                     $badOrder = true; // если в заказе есть товары не из 1С, то не обрабатываем его
    291                     break;
    292                 }
    293             }
    294             if ($badOrder) {
    295                 $log->addLog(sprintf(_t('Orders1CExchangeExporter.SkipOrder', 'Пропускаем заказ %s'), $order->ID), 'warning');
    296                 continue;
    297             }
    298
    299             if (count($productsID)) {
    300                 foreach($productsID as $itemID) {
    301                     DataObject::delete_by_id('OrderItem', $itemID);
    302                 }
    303             }
    304
    305             $order->flushCache();
    306             $order->write(false, false, true);
    307             $ordersCount++;
    308
    309             foreach($orderData->ЗначенияРеквизитов->ЗначениеРеквизита as $entry) {
    310                 if (($entry->Наименование == 'ПометкаУдаления') && ($entry->Значение == 'true')) {
    311                     $order->delete();
    312                 }
    313                 if (($entry->Наименование == 'Проведен') && ($entry->Значение == 'true')) {
    314                     $order->Status = 'Query';
    315                     $order->Update1C = 1;
    316                     $order->write();
    317                 }
    318                 if (($entry->Наименование == 'Отменен') && ($entry->Значение == 'true')) {
    319                     $order->Status = 'AdminCancelled';
    320                     $order->Update1C = 1;
    321                     $order->write();
    322                 }
    323                 if (($entry->Наименование == 'Отгружен') && ($entry->Значение == 'true')) {
    324                     $order->Status = 'Complete';
    325                     $order->Update1C = 1;
    326                     $order->write();
    327                 }
    328             }
    329         }
    330         $log->addLog(sprintf(_t('Orders1CExchangeExporter.ProcesedOrder', 'Обработано заказо %d'), $ordersCount));
    331     }
    332 }

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -