Как построить цепочку асинхронных вызовов




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

68 Comments

  1. vipetrov2

    Можно было бы и по проще сделать. Все вопросы записать в список значений или написать функцию для конвертации номера вопроса в текст вопроса.

    Если ПараметрыСценария = Неопределено Тогда
    // первый вход в процедуру выполняется без параметров
    ПараметрыСценария = Новый Структура;
    ПараметрыСценария.Вставить(«ТекущийШаг», 0);
    Иначе
    Если Результат <> КодВозвратаДиалога.Да Тогда
    Возврат;
    КонецЕсли;
    ПараметрыСценария.ТекущийШаг = ПараметрыСценария.ТекущийШаг + 1;
    КонецЕсли;
    
    Если СписокЗначений.Количество() = ПараметрыСценария.ТекущийШаг Тогда
    ВыполнитьОсновныеДействия();
    Возврат;
    КонецЕсли;
    ТекстВопроса = СписокЗначений[ПараметрыСценария.ТекущийШаг];
    //ТекстВопроса = ПолучитьТекстВопроса(ПараметрыСценария.ТекущийШаг);
    //Если ТекстВопроса = Неопределено Тогда
    // ВыполнитьОсновныеДействия();
    // Возврат;
    //КонецЕсли;
    Оповещение = Новый ОписаниеОповещения(«ВыполнитьСценарийСДиалогами», ЭтаФорма, ПараметрыСценария);
    ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
    

    Показать

    Reply
  2. json

    (1) Попробуйте представить, как вы будете реализовывать предлагаемый вами вариант в реальной жизни. Например, вопросы могут иметь различные коды возврата, а не только Да/Нет, перед вопросом возможно нужно будет делать проверку, и задавать вопрос, только если она не прошла. После ответа на вопрос пользователя иногда потребуется выполнить какое-нибудь действие, а не просто перейти к следующему шагу. Не всегда нужно прерывать сценарий после ответа Нет. Перечисленными мною примерами реальная жизнь не ограничивается. Предлагаемая в публикации схема мне кажется более гибкой и наглядной. Пример в ней упрощен, для облегчения понимания описываемого приема. Кстати, в приложенных к публикации файлах, примеры чуть поинтереснее, чем в публикации

    По поводу того, что вариант со списком проще — не готов согласиться, но тут каждый может реализовать так, как считает правильным.

    Reply
  3. vandalsvq

    (0) а промисы все равно удобнее ))))))

    Reply
  4. json

    (3) тут не поспоришь))

    Reply
  5. unichkin

    … Снят вопрос)

    Reply
  6. s22

    ждем async await

    Reply
  7. Synoecium

    Интересный подход, сам задумывался над такими неудобствами управляемых форм. Возникло такое предположение, что есть смысл пробрасывать через ПараметрыСценария данные, которые используются в нескольких проверках. Т.е. проверяем наличие в структуре некоторых «кэшированных» переменных и если они не заполнены тогда заполняем их. Тогда не надо будет их получать в каждой проверке/итерации.

    Reply
  8. starik-2005

    Можно деревом описать сценарий. В корне — вопрос, в подчиненных ветках — ответы, в подчиненных ответам ветках — следующие вопросы. Ну и так далее. Также можно в дереве добавить ключ перехода на любой из уровней, и если он заполнен — получить новые вопросы/ответы из соответствующего узла, а если не заполнен — из подчиненного.

    Типа так:

    Вопрос

    1 — Ответ 1

    2 — Вопрос 2

    3 — Ответ Х

    4 — Ответ У

    5 — Ответ 2

    6 — Вопрос 3

    7 — Ответ Z

    8 —- — ИД = 2 (переход к ветке вопросов с ИД 2)

    Чем не метод?

    Reply
  9. json

    (9) посмотрел в карточку автора этого комментария. Все комментарии в таком стиле. Никакого конструктива. Везде подобные бессмысленные фразы. Даже спрашивать не буду, что его не устроило.

    Reply
  10. starik-2005

    (10) решил тоже посмотреть. Как оказалось, у нас в Вами разные взгляды на адекватность )))

    Reply
  11. json

    (11) Я не упоминал адекватность. Я лишь высказал свое наблюдение, что такого рода комментарии неконструктивны и бессмысленны.

    Меня всегда удивляли подобные комментаторы, которые бросают вот такие фразы. Ведь толку от них ноль.

    Ну не нравится тебе статья, пройди дальше, не читай. Ведь никто же не заставляет. Возможно другим она будет полезна.

    Бывает, что не согласен с точкой зрения автора — значит аргументируй. Может действительно у человека есть здравая мысль. Пусть не скрывает ее.

    А какой смысл от пустых обвинений?

    Reply
  12. Fragster

    (6) 1с вообще могла это прозрачно для прикладного программиста сделать. Но, поскольку «азаза! в хруме не работает!!!» залепили костыль за неделю, а переделывать не стали, чтобы не ломать обратную совместимость. Наоборот, только усугубляют все, добавляя всякие «начать…» (см. двоичные данные), не понимая, что это влечет разный код на клиенте и на сервере, которого становится всё больше и больше. Ну и вермишель с этими оповещениями.

    Остается надежда на 8.4/9.0…

    Следующий такой ошибкой стала «защита от опасных действий», но она не столь сильно влияет (просто «защита» не защищает, а немного усложняет жизнь программистам).

    Reply
  13. Evil Beaver

    Вы, возможно, удивитесь, но я хочу сказать, что цепочки асинхронных диалогов это вселенское зло. Если ваш UI/UX такое использует, то он плохо спроектирован. И исключительно из-за неудачного дизайна UI возникла потребность изобретения несомненно интересного решения, приведенного в статье. Беда только в том, что его можно было не изобретать, пересмотрев подход к взаимодействию с пользователем.

    Модальность не нужна. Попытки ее вернуть, применяя указанные обходные решения, ни к чему хорошему не приведут. Много вы видите в интернетах «цепочек модальных диалогов» на сайтах? А пользоваться удобно, как ни странно.

    Reply
  14. Fragster

    (14) вот пример от учебного центра 1с: абстрактный блокнот, если текст модифицирован, то вопрос, «сохранить?», если новый, то показать диалог выбора имени, если файл существует, то показать вопрос о замене. Это стандартное поведение большинства программ. Отказываться от модальности не следует. другое дело, что 1с смешала модальность (т.е. недоступность частей интерфейса кроме «модальных») и асинхронность.

    Текущие диалоги, вызываемые через ПокахатьXyz() — модальные. И ничего не мешало сделать эту модальность «асинхронной», т.е. не блокирующей основной поток на клиенте и с использованием старого синтаксиса.

    Описание «правильного» костыля http://www.1c-uc3.ru/video.html в видеоуроках (буэээ..).

    Reply
  15. Evil Beaver

    Ну приведенные примеры они не требуют «цепочки». По сути, нужно выбрать какой диалог показать, и показать его немодально. И вообще, сей пример синтетический (т.е. надуманный). Было бы интересно обсудить что-то из жизни. Я такой пример придумать не смог….

    И да, под «модальностью» в предыдущем сообщении я понимал именно блокирующую текущий поток модальность, а не сам концепт «модального окна».

    Reply
  16. Fragster

    (16) вопрос даже не в цепочках. вопрос в том, что, например, диалог перед записью формы уже становится невозможным без своей кнопки «записать и закрыть». ну и различие клиентского и серверного кода (подключить внешнюю компоненту/начать подключение, двоичные данные, и прочее), катастрофическое увеличение сложности и количества обслуживающего кода — всё это накапливается как снежный ком, хотя может быть скрыто от программиста 1с.

    Reply
  17. Fragster

    (16)

    По сути, нужно выбрать какой диалог показать

    а если не надо сохранять? а если надо перевыбрать файл/изменить имя вместо перезаписи? То, что в данном случае этот модальный диалог в цикле — системный, глобально ничего не меняет.

    Reply
  18. vipetrov2

    (2) Если фантазию включить, то можно вместо Списка Значений, сделать Таблицу Значений с 2-мя столбиками: текст вопроса и правильный ответ. Почему мой вариант не проще? Надо адаптировать под конкретный случай только 1 процедуру, т.е. заполнить таблицу вопросов и ответов. И мой вариант гораздо производительнее потому что на 10 вопросе у тебя будет 10 раз проверяться тот или не тот шаг, а у меня с сразу вопрос задается.

    А вообще буквально недавно надо было на стороне клиента сделать НачатьПроверкуСуществования(..) и потом если нет каталога, создать его НачатьСозданиеКаталога().

    Но бывает еще сложнее задача когда надо через цикл сделать несколько вызовов НачатьХХХ, потом после оповещения еще вызвать НачатьХХХ и при этом у процедур оповещений разное количество параметров. Например у НачатьУдалениеФайлов процедура оповещения имеет только 1 параметр.

    Reply
  19. json

    (16)

    Вот примеры из жизни (было несколько месяцев назад при доработке ерпи)

    Требуется добавить проверки в заказ поставщику перед действием Провести и закрыть

    1. Проверить, что сумма заказа соответствует бюджету. Вывести вопрос

    2. Проверить, что остаток после заказа плюс остаток на складе — не превысит норму. Если превысит — вывести вопрос.

    3. Проверить ограничения, накладываемые поставщиком (что количество товара больше или равно минимальной партии). Вывести вопрос

    При проведении поступления

    1. Проверить соответствие цен в поступлении ценам в заказе. Если различаются — вывести сумму отклонения и вопрос.

    2. Проверить соответствие количества в поступлении количеству в заказе. Если некоторый товар не пришел, то предложить: ничего не делать, перенести в новый заказ (открыть мастер создания заказа поставщику), удалить из текущего, вернуться к редактированию.

    Эти проверки были добавлены поверх существующих типовых. Нетрудно догадаться, что это все будет развиваться и усложняться со временем. Через некоторое время у заказчика появятся новые хотелки.

    Reply
  20. boln

    Респект за еще один подход к разруливанию «асинхронных пробок».

    Сам почти 2 года назад озаботился этим. Применил сущность типа «стек» для организации очередности возврата глубоких асинхронных вызовов. Сделал даже видеокурс для УЦ-3:

    http://www.1c-uc3.ru/video.html

    Reply
  21. Evil Beaver

    (21)

    1. Проверить, что сумма заказа соответствует бюджету. Вывести вопрос

    2. Проверить, что остаток после заказа плюс остаток на складе — не превысит норму. Если превысит — вывести вопрос.

    3. Проверить ограничения, накладываемые поставщиком (что количество товара больше или равно минимальной партии). Вывести вопрос

    Зачем три вопроса вместо одного окна с перечнем проблем? Вы, пожалуй, невнимательно прочитали мое первое сообщение. Потребность в цепочках вопросов возникает при некачественно спроектированном взаимодействии с пользователем. Три вопроса вместо одного — это некачественное взаимодействие. Вырождающееся впоследствии в необходимость разработки «цепочек вопросов в асинхронном режиме».

    Reply
  22. Fragster

    (23) выше бы приведен пример с работой с файлами. Например пакетная выгрузка чего-либо в папку: проверить существование (асинх), при наличии — задать вопрос про очистку (асинх), очистить(асинх), скопировать файлы (асинх), отрапортовать пользователю.

    вторая ветка — при отстутсвии — создать (асинх), скопировать файлы (асинх), отрапортовать пользователю.

    Reply
  23. json

    (23)

    Согласен, что некачественное и что лучше сделать одну форму.

    Но тут возникают противоречия.

    Во-первых, если уже есть решение, которое построено через вопросы. Что делать? Часть вопросов будет в одной форме, а часть в отдельных окнах. Переделывать?

    Во-вторых, бюджет на то, чтобы нарисовать интерфейс — больше, чем на более простое решение.

    В-третьих, что делать, если нужно в одной из проверок открыть другую уже существующую форму (например, мастер создания Заказа поставщику)?

    В-четвертых, был еще такой случай, что сначала нужна была одна проверка. Сделали через вопрос. Потом понадобилась еще одна. И никто уже написанное другим разработчиком не переделывает и в бюджет не закладывает.

    Но мне подход без цепочки тоже нравится больше, в том случае есть возможность его использовать

    Reply
  24. boln

    (23)

    Потребность в цепочках вопросов возникает при некачественно спроектированном взаимодействии с пользователем. Три вопроса вместо одного — это некачественное взаимодействие. Вырождающееся впоследствии в необходимость разработки «цепочек вопросов в асинхронном режиме».

    А вот это не факт. Выше уже говорилось про «абстрактный блокнот», но эта последовательность задания вопросов характерна и для прикладной обработки, например «Консоль запросов» и «Консоль СКД».

    Сможете предложить решение без цепочки вопросов?

    Reply
  25. herfis
  26. json

    (7) исправил пример в публикации по вашей рекомендации. Основная процедура вроде как упростилась.

    Также немного усложнил пример, чтобы продемонстрировать гибкость данного способа

    Reply
  27. json

    (19)

    Вы скорее всего имели не таблицу значений, а массив структур, т.к. действия выполняются на клиенте

    Но даже если мы будем использовать такую коллекцию, то нам придется выбирать между двумя невыгодными вариантами:

    1. Либо писать процедуру обхода такой коллекции для каждого сценария. Тогда каждый такой обход будет содержать специфические для данного сценария действия. В чем же тогда простота?

    2. Либо нужно написать очень универсальный метод, в котором каждый элемент коллекции шагов должен содержать множество ключей, типа «СоответствиеДействийИОтветов», «ОтветДляПрерыванияСценария» и т.п. в таком духе. Похожий подход с массивом структур уже реализован в БСП, правда он используется для другого. Если интересно, можете посмотреть в демо БСП (2.3.2) внешнюю обработку ЗагрузкаНоменклатурыИзПрайсЛистаСоСценарием.epf, а в ней функцию СформироватьСценарий(). Я предполагаю, что если попытаться написать универсально, то получится что-то подобное. Там довольно большой объем служебного кода, трудно быстро понять, какие параметры за что отвечают. Хотя этот механизм и рабочий, но порог вхождения в работу с ним — довольно высокий.

    В моем примере (я его чуть усложнил) всего три универсальные обслуживающие процедуры и одна основная. При этом читаемость (описания шагов) не страдает, по сравнению с описанием сценария, а универсальность намного выше

    Reply
  28. vandalsvq

    (23) на самом деле лапша с асинхронными вызовами бывает весьма забавной. И даже если там нет вопросов. Например: пользователь выбрал файл, файл либо xml, либо zip-архив.

    И так поток действий…

    1. Проверка наличия файла

    2. Проверка свойств файла (для получения расширения)

    3. Если архив распаковка

    4. Если архив проверка существования файла в распакованном каталоге

    5. Загрузка данных файла

    Большинство этих действий асинхронны, получится целый набор описаний оповещений которые должны сработать последовательно (ну или в обход). Вот в таких случаях конечно удобно, если бы был менеджер асинхронных действий.

    Хотя в тех же js promise у меня был бы очень простой код:

    getFile() // обещаем что сообщим когда получим файл
    .then(getFileAttr) // обещаем что сообщим когда получим свойства файла
    .then(unzipFile) // обещаем что сообщим когда распакуем, а если не архив то вернем resolve
    .then(loadFileData) // загружаем данные
    .catch(errorHandler) // перехватим ошибку

    Я не люблю несколько вопросов, предупреждений и прочих всплывающих окон подряд. Тут я согласен, что надо пересматривать алгоритмы, выводить одно сообщение с набором нестыковок. Но вот что касается не диалоговых асинхронных вызовов, тут пока не очень удобно работать.

    Reply
  29. boln

    (30)

    Большинство этих действий асинхронны, получится целый набор описаний оповещений которые должны сработать последовательно (ну или в обход). Вот в таких случаях конечно удобно, если бы был менеджер асинхронных действий.

    Угу, проходили все это на практике. Отсюда и появился «стек оповещений» 🙂

    Но развитых средств асинхронного программирования в языке 1С вряд ли приходится ожидать. Во-первых, все эти асинхронные заморочки возникают только для веб-клиента — а этот вариант работы пользователя все же не преобладающий, хотя спектр его применения и растет. А во-вторых, компилятор — самая консервативная и трудно поддающаяся развитию часть платформы. Заметили, наверное: возможности платформы, начиная с 8.2, расширяются только за счет увеличения числа классов объектов платформы, а не развития языковых средств и конструкций.

    Reply
  30. starik-2005

    (31) а мне кажется, что язык тоже развивается. Асинхронные методы для вызова диалогов, подключения внешних компонент, чтения файлов и прочее — это вполне правильное движение в нужную сторону. Думаю, что со временем 1С откажется от тонкого клиента в пользу браузера и от конфигуратора в пользу EDT. Дальше все будет работать в модели сервиса, когда система 1С будет встроена в технологический стек компании, отвечая за свой локальный функционал бухгалтерской базы. Если они дойдут в развитии языка до описания ОРМ, то это будет весьма большой шаг вперед навстречу производительности, которой в 1С сейчас нет, ибо нет возможности использовать ни шардинг, ни кеширование объектов (в том же Redis’е, например, или Memcache). И это весьма ограничивает 1С, как продукт.

    Сейчас все языки двигаются в сторону асинхронности, многопоточности, функциональности. Лямбда-функции и рекурсивные механизмы активно внедряются даже в С++, который раньше не был таким функциональным. И сделано это, полагаю, для лучшей распараллеливаемости, ибо функциональная парадигма весьма способствует этому.

    Reply
  31. Fragster

    (32) это — не развитие. Развитие — это не «больше строк для тех же действий» и «более запутанная структура программы», а как раз наоборот.

    в js уходят от этого в сторону промисов, до этого — были замыкания и люмбды, которые помогали писать в болееменее синхронном стиле (по крайней мере строки визуально шли в одном месте и по порядку), в дотнете — в сторону async/await. и на момент появления «асинхронности» в 1с — эти механизмы уже были.

    Ценность 1с как раз в том, что она скрывает от прикладного программиста все эти низкоуровневые дела. Вы просто не пытались сделать обновление на новую версию программы, скажем, с изменением структуры данных, причем так, чтобы это прошло безопасно, не на 1с.

    Reply
  32. starik-2005

    (33) так не на 1С применяются миграции в ОРМ, а в плане кода — рефакторинг идет от объектов в ООП (тот же S.O.L.I.D.), когда все максимально отделено друг от друга и один объект — одна четкая конкретная функция, вместо генерации универсальных велосипедов.

    В 1С кое-что, конечно, с ног на голову, но асинхронность как раз позволяет отделить механизм отображения от механизма обработки результата, выделив код обработки отдельно. При том никто не мешает выделить функции оповещения в отдельный модуль и поддерживать оные там. Мне, например, стало куда комфортнее обрабатывать множество реакций на события в одной асинхронной функции, определяемой в описании оповещения.

    По поводу асинхронности, то в том же js даже для генерации кадра используют асинхронную функцию requestAnimationFrame, до этого использовали таймаут. Промисы — это супер, может быть и в 1С это реализуют, но тут, конечно, не все так просто.

    Я не говорю, что 1С — штука идеальная. Она прежде всего очень медленная — это основное. При этом она позволяет сделать какой-нибудь интерфейсный прототип с хранимыми в СУБД данными достаточно быстро (не быстрее, конечно, чем Tcl/Tk, но тоже вполне сопоставимо по времени).

    Reply
  33. boln

    (32)

    а мне кажется, что язык тоже развивается. Асинхронные методы для вызова диалогов, подключения внешних компонент, чтения файлов и прочее — это вполне правильное движение в нужную сторону.

    Это не языковые конструкции, а просто расширение объектной модели. В других языках асинхронность реализуется именно через языковые конструкции. Поэтому там просто, а в 1С сложно.

    Reply
  34. starik-2005

    (35) ну там она тоже реализуется по-разному. Если говорит о промисах, то это — да, языковая конструкция, но в пределе это метод соответствующего объекта со своим прототипом. В 1С обработчик оповещения — это тоже отдельный объект. Другое дело, что мы не имеем доступа к его прототипу (интерфейсу) для переопределения или расширения. Фактически промис — если говорим о нем, как о расширении языка — это функция с двумя аргументами-функциями, возвращающая еще один промис, который также может возвратить промис и так далее. Очень удобно цепочки асинхронные строить. Но это всего лишь функция — не более. 1С тоже может такую функцию напилить, просто она не умеет функции иначе как в объекте описания оповещения передать.

    Reply
  35. boln

    (36) Налицо тенденция использовать языковую конструкцию вида Async:

    https://msdn.microsoft.com/ru-ru/library/windows/apps/hh464924.aspx

    Ну, причина, в общем, извинительная — делалось на скорую руку, под ограничения браузеров.

    Есть и еще одна причина глобального характера: 1С продает не платформу, а готовые решения. Поэтому им нафиг не вперлось ни ООП, ни вообще какое-либо развитие языка: команду своих 30-40 штатных разработчиков легко построить, чтобы писали на том, что дают, и хотелки-помечтовки свои при себе держали. А проблемы сторонних разработчиков, пишущих с нуля, при таком целевом раскладе никого не волнуют.

    Reply
  36. starik-2005

    (37) сторонним разработчикам никто не мешает писать на чем угодно, используя 1С как ящик для красивых отчетиков пользователям — этакий BI. Зашоренность сторонних разработчиков и их полное погружение под желтого гиганта — это их собственные сексуальные проблемы нереализованной юности. Кому надо — тот 1С-ом не ограничивается.

    А мелкософтовский MSDN по сцылке говорит, что это для 8-й венды, а кто на 10-ке творит — нажмите другую сцылку. Но асинхронность — это не дань моде, а попытка утилизировать дополнительные процессорные ядра.

    Просто, как мне кажется, некоторых студентов в ВУЗах переучивают излишне, а потом они, видя nginx или redis, которые позиционируются как безблокировочные однопоточные приложения, начинают всем говорит о том, что вот, мол, асинхронность — зло, многопоточность — медленная. Ну это дань нашему отставшему образованию — не более. На сайте Интела для разработчиков прямо с порога про многопоточность втирают, что без этого ни один уважающий себя программист жить не может в мире современном.

    Reply
  37. boln

    (38)

    сторонним разработчикам никто не мешает писать на чем угодно, используя 1С как ящик для красивых отчетиков пользователям — этакий BI. Зашоренность сторонних разработчиков и их полное погружение под желтого гиганта — это их собственные сексуальные проблемы нереализованной юности. Кому надо — тот 1С-ом не ограничивается.

    Это, конечно, так. Кому надо, тот внешние возможности найдет способ подтянуть.

    Я просто предупредил, чтобы не ждали некоторые от встроенного языка платформы 1С:Предприятие чудес вроде ООП и разных прочих async’ов/await’ов — и сказал, почему я так считаю.

    Reply
  38. Yashazz

    Погодите, стоп. Т.е. вся идея этой публикации — замыкание на одну процедуру, в которой всё крутится? Господа, но это ж лютый баян, это ещё года три назад делали и публиковали. Или я не вижу некоей новизны?

    Ну и, тогда уж, надо учесть, что не у всех асинхронников завершающая процедура имеет два параметра, и что платформа не понимает юмора, как обязательные они объявлены или нет, поэтому одной супер-процедурой всё равно не обойтись. По количеству аргументов, у меня таких «ловчих» обычно 3-4 штуки на разные случаи.

    Reply
  39. boln

    (40)

    Так вот, нахрен этот веб-интерфейс не нужен.

    Вероятно, это прицел на облачные технологии:

    http://v8.1c.ru/fresh/whatis.htm

    Они там пишут:

    пользователи сервиса используют размещенные в сервисе прикладные решения через Интернет с помощью обычного интернет-браузера или тонкого клиента

    Т. е. для выхода в облако через мобильное устройство, где платформу — тонкий клиент — не установишь.

    Reply
  40. Yashazz

    (42) Ну только если… Всё равно это даже не половина рынка. А в моей практике обычно разговоры про облака заканчиваются обычным терминалом на обычный хороший сервер, за которым ухаживают спецы, как и за конфой. И всё.

    Reply
  41. Bonov

    (43) вот уж не согласен, что 1с только для бухов и что веб интерфейс не нужен вовсе. Наоборот, я за развитие платформы в этом направлении. Это универсальность, безопасность и функциональность. А так же уже возможность отказаться от винды в принципе и других сторонних приложений. Я и наш продукт идем по пути интеграции всего учета в 1с, начиная от документов, бухгалтерии и заканчивая телефонией, факсами, смс, обменов с подрядчиками и клиентами, веб сервисов для клиентов, мобильных приложений и пр.

    Reply
  42. starik-2005

    (43)

    Всё равно это даже не половина рынка.

    Как-то йаху сказало студентам, что их поисковый движок им неинтересен. Ну и где сейчас йаху, а где сейчас гугл. Через три года все это убожество типа толстых клиентов окончательно перестанет поддерживаться, решения будут активно переносится на тонкий клиент и веб-платформу. Потом админам надоест переустанавливать клиентское ПО, и все медленно и верно мигрируют в браузер. Большая часть не 1С мира давно уже живет в браузере, одни желто-красные тормозят, а сообщество им в этих тормозах помогает )))

    Reply
  43. starik-2005

    (44)

    заканчивая телефонией, факсами, смс

    Ну я надеюсь Вы астерикс на 1С не стали писать, а взяли готовый? В этом плане велосипеды не всегда полезны, а с учетом доступности 1С даже в продуктиве весьма далекой от хотя бы 99% с APDEX 90, переносить все жизненные вещи в 1С просто саботаж против своей организации.

    Reply
  44. Yashazz

    (44)

    Я и наш продукт идем по пути интеграции всего учета в 1с, начиная от документов, бухгалтерии и заканчивая телефонией, факсами, смс, обменов с подрядчиками и клиентами, веб сервисов для клиентов, мобильных приложений и пр.

    Когда я был молодой и наивный мечтатель, я тоже всем предлагал и всячески продвигал такое в компании, где работал. Компания была не из мелких, поле было непаханое. Прошло много лет. Бухгалтерия работает в 1С. Остальное всё так же на уровне менеджерских файликов, вордов-эксельчиков, кривых поделок на дельфе и си-шарпе для CRM, фигулек для мобильного приложения ещё на чём-то… Поменьше громких фраз, как космические корабли бороздят известно что))) Если бизнесу это не припрёт совсем, то никакой супер-1С не будет. Собственно, и бухгалтеры рады бы работать на чём-то более адекватном, чем БП 3.0, но отчётность сдавать надо, поэтому вынуждены. Так-то.

    Reply
  45. Yashazz

    Глюк)))

    Reply
  46. Yashazz

    (45)

    убожество типа толстых клиентов

    Убожество — это то, что 1С называет тонким клиентом. Убожество — это то, что 1С называет немодальностью и асинхронностью. Убожество — это интерфейс Такси. По всему — по степени удобства для разработчика и для пользователя, по быстродействию разработки и работы. Вот что истинное убожество.

    Попробуйте объяснить клиенту, почему УТ 11, пустая и новая, дико тормозит при попытке открыть «Все функции», или любую форму списка, или вообще при нажатии любой кнопки, а его, клиента, огроменная УТ 10.3 за 10 лет всё делает мгновенно) Почему треть экрана в «Такси» занята неотключаемой пустотой, а чтоб смотреть данные, приходится всё время скроллить форму.

    Попробуйте объяснить мне, почему на клиенте в 1С нет объекта «Таблица значений», или метаданных, или почему нельзя управлять составом данных формы, передаваемым на сервер, или почему, на самом деле, сделали этот адский костыль под названием обработка оповещения.

    Почему так тормозит конфигуратор при разработке управляемой формы, и почему эта якобы «управляемая» в разы менее доступна для настройки дизайна, чем обычная, тормозит сильнее и жрёт больше ресурса.

    Короче говоря — я много лет занимался разработкой под тонкий, веб, с управляемыми формами. И мой вывод — это уродство.

    все медленно и верно мигрируют в браузер.

    В этом нет ничего хорошего, равно как и в тенденциях развития софта вообще. После 2010 года софт вообще массово превратился в полное гуано, целиком зависящее от сети. Сравните нормальный, а оттого популярный, 2010-й аутлук, и ублюдочный 2013-й, к примеру. Ну и главное. Пока в базах данных будут сведения, за которые руководство будет опасаться, а интернет не будет 100% безопасным никогда, до тех пор эти базы данных будут где угодно, но не торчать веб-клиентами в браузерах.

    Кстати о браузерах: вот сейчас ИС сглючил при отправке этого текста. Вы себе представляете восторг менеджера, который час набивал документ, а потом сеть/браузер/1С глюканули, и всё пропало? А я вот работал по сети с СППР, где это было нормой, и никогда больше не порекомендую своим клиентам использовать веб-клиент 1С. Но, конечно, если ваша задача — впарить «моднявый» продукт в тренде «все в сеть», а дальше трава не расти, то, конечно, флаг в руки.

    Reply
  47. starik-2005
    Reply
  48. Yashazz
    По поводу немодальности и асинхронности, то тут у нас с Вами совершенно разное понимание. Мне, например, гораздо удобнее напилить управляемую форму любой сложности, чем потом мучиться с привязками обычной формы. Да и сама 1С вечно натворит руками программистов за тарелку супа с обычными формами кучу кривых привязок, скрытых панелей, невидимых страниц — потом замучишься искать, где там и что в каком элементе спрятано. Объединить старую и новую формы нереально, в управляемой же форме все элементы в дереве, БСП позволяет просто и легко привязывать команды и дополнительные реквизиты к форме.

    Управляемая форма «любой» сложности сложнее 10-15 групп — начинает вешать конфигуратор. На любом известном мне релизе. Привязки позволяют, хоть и помучившись, сделать то, чего на УФ просто ваще никак не сделать. Лучше плохо ехать, чем хорошо стоять, так считаю. Мог бы сказать насчёт плохого танцора и привязок, которые на самом деле элементарны, да Вы и сами поняли.

    Скрытые панели и элементы? Так вот почему невидимый элемент в обычных формах виден, а в управляемых — нет. Это чтоб нам жилось легче! Искать замучились? А дерево объектов формы не пробовали юзать, оно в обычных очень даже есть, а? Или Вы про него не в курсе?

    Объединить, говорите, нереально? То-то при копипасте в обычных формах всё куда надо плюхается, а в управляемых либо не копируется, либо криво (команды вяжутся не пойми куда, объекты не вяжутся к командам, пути к данным полей бьются, ряд случаев просто кончается вылетом с дампом).

    Про БСП не буду. Во-первых, это уже не о платформе речь, а во-вторых, не хочу об этой дряни вообще разговаривать.

    Reply
  49. Yashazz
    Браузеры давно уже вполне безопасны, ибо HTTPS начиная с TLS 1.1 безопасен. Настроить подобное внутри сети вообще не является проблемой — достаточно самоподписанного сертификата, сгенерированного на веб-сервере. Но в действительности защиту информации дает не шифрование трафика, а ролевое разделение и нескомпрометированные учетные данные. Внутри корпоративной сети как раз доступ к информационной системе из браузера — это вполне здоровая практика.

    Объясните это бизнесмену, поднявшемуся в 1990-е. Что в сети — то уязвимо. Безопасен только сервер в подвале за решёткой, и флешка в кармане гендира.

    Reply
  50. Yashazz

    Кстати, с абзацем насчёт асинхронности и тарелки супа — соглашусь. Да, по-хорошему, должно работать так. Но Вы правильно описали, что меры не знают и, делая, не всегда думают.

    Очень хочется управлять кэшированием на клиенте и отправкой на сервер более гибко. Как в нормальных мобильных приложениях, если девайс вдруг без связи. Хочется уметь рулить временем жизни этих данных. Хочется рулить отправкой на сервер гибче, чем «БезКонтекста» или с контекстом. Да только увы.

    Reply
  51. starik-2005

    Не люблю спорить с пенсионерами — слишком скучно.

    Reply
  52. Bonov

    (47) Вы просто не смогли, а я смог, и у нас нет ни одного сотрудника, не работающего в общей базе 1С. Астериск конечно же отдельный, но все же тоже интегрированный. И куча клиентов, которые по вебу имеют доступ к базе. Быть может, у меня нет особых проблем, потому что все написано с нуля и из других конф и БСП взято всего лишь несколько универсальных функций. А вообще с костылями, тормозами и усложнившейся логикой новых продуктов я конечно же согласен.

    Reply
  53. Fragster

    Вот фрагмент асинхронного кода на js:

     client.callApi(‘messages.getDialogs’, {offset_date: 0, offset_id: 0, offset_peer: peer, limit: 0})
    .then(result => { // тут оказываемся в конце асинхронного вызова
    let chats = result.chats.list;
    return chats.reduce((promise, elem) => {
    return promise.then((resArray) => {
    if (elem.creator) { // если свойство creator установлено, то делаем еще один асинхронный вызов
    return client.callApi(‘messages.getFullChat’, {chat_id: elem.id}).then((res) => { // по завершению которого
    resArray.push(res); // кладем результат в массив-накопитель
    return Promise.resolve(resArray);
    });
    } else {
    return Promise.resolve(resArray); // если ничего не надо делать — вызываем метод-пустышку (типа ВыполнитьОбработкуОповещения)
    }
    });
    }, Promise.resolve([]));
    }).then(result => { // обрабатываем результат

    Показать

    он вызывает асинхронный метод messages.getDialogs, результатом является массив. Затем выполняется обход массива с вызовом асинхронного метода для каждого элемента, последовательно (еще есть Promice.all, который запускает всё параллельно, но сервер за такое банит :))

    результаты каждого вызова кладутся в массив. Когда все вызовы завершатся, переходим в //обрабатываем результат

    Не используется ни одной глобальной переменной.

    Как подобное реализовать в 1с (например рекурсивный обход со всякими файловыми функциями начатьполучение и асинхронное чтение из файлов) — плохо представляю.

    хотя данный пример кода показывает, что в js все тоже не так гладко, но, по крайней мере, такие асинхронные цепочки получаются локализованными и последовательными. Также пример показывает асинхронное ветвление, которое в 1с превращается в ещё бОльшее спагетти.

    Reply
  54. boln

    (53)

    Объясните это бизнесмену, поднявшемуся в 1990-е. Что в сети — то уязвимо. Безопасен только сервер в подвале за решёткой, и флешка в кармане гендира.

    Но ведь и это поколение не вечно — стоит ли на него ориентироваться стратегически? Когда-то бабушкам приходилось объяснять, что электричество лучше керосина, а дедушкам — что автомобиль лучше лошади, хотя эти новшества и имеют свои собственные риски и уязвимости…

    Reply
  55. Yashazz

    (55)

    Не люблю спорить с пенсионерами — слишком скучно.

    Тогда тем более нам с Вами, молодым, есть о чём поспорить, только уже не тут, где оффтопим, а, например, в личке)

    Reply
  56. Yashazz

    (56) Хорошо, что смогли. Только не думайте, что это Ваша заслуга. Это заслуга административного ресурса, который железными палками загнал всех в Вашу систему. Не имеет значения, самописная она или типовая. Имеет значение лишь одно — есть ли тот, кто заставит всех работать в 1С, или такого нет. Если нет — хоть наизнанку вывернитесь, но ничего не изменится; на Ваш функционал будут класть и продолжать кропать эксельчики. Если есть — работать будут хоть в ERP, колоться и жрать кактус, хоть в нормальной конфе. А от нас с Вами, коллега, в этой ситуации зависит исчезающе мало.

    Reply
  57. Bonov

    (60) Раз Вы не зная ни меня, ни мою компанию, ни мою роль в процессе, ни качество выстроенной системы, делаете какие то выводы, то грош цена любым Вашим высказываниям…

    Любой сотрудник будет работать там, где ему удобнее. И я считаю, что именно задача ИТ сделать такую инфраструктуру, чтобы людям было УДОБНО. А единая система, которая позволяет выполнять ВСЕ действия, не переключаясь на другие не интегрированные с ней программы, именно таким решением и является. Именно таким путем идет 1С. И я здесь вместе с ней, потому что мой разум не ограничен мыслями, что 1С — это только бухгалтерия.

    Reply
  58. starik-2005

    (61)

    Любой сотрудник будет работать там, где ему удобнее.

    Невозможно не согласиться. Другое дело, что зачастую удобнее — это и быстрее тоже. Если для получения отчета бухгалтер будет ждать полчаса (да, такое бывает), то она в это время чаю заварит и с тортиком с коллегами попьет. Но если это входящий вызов в коллцентре и сотруднику просто необходимо знать, что за клиент позвонил, то тут уже и трех секундной реакции не хватит — нужна реакция в доли секунды. Именно по-этому мы в свое время не стали тянуть все в 1С, а сделали для операторов коллцентра отдельный интерфейсик в вебе, в который автоматически падала информация о звонящем. И лицензии целы, и операторы довольны. Но если кому-то не жалко лицензий для оператора коллцентра, то я рад тому, как идут его дела — видимо денег некуда девать, Отдайте мне!

    Reply
  59. Yashazz

    (61)

    Раз Вы не зная ни меня, ни мою компанию, ни мою роль в процессе, ни качество выстроенной системы, делаете какие то выводы, то грош цена любым Вашим высказываниям…

    На ИС Ваш профиль не информативен, публикаций у Вас нет. Я высказался с позиции программиста 1С. Если Вы крутой босс, тогда мои Вам извинения. И перестаньте пихать всюду качеств системы, оно не играет никакой роли. Кривая дрянь типа первых УТ 11.2 и 11.3 пошла «на ура» просто потому, что все были вынуждены.

    Любой сотрудник будет работать там, где ему удобнее. И я считаю, что именно задача ИТ сделать такую инфраструктуру, чтобы людям было УДОБНО. А единая система, которая позволяет выполнять ВСЕ действия, не переключаясь на другие не интегрированные с ней программы, именно таким решением и является.

    Сотрудник будет работать там, где ЕМУ удобнее. А удобнее — это привычнее. А привычнее — это в экселе, ворде, блокноте, на коленке. ИТ тут бессильна. Есть хорошая ковбойская поговорка: «и один человек может привести лошадь на водопой, но даже 10 не заставят её пить». Тут что-то может только адм.ресурс. Ну, вам повезло, но это исключение. Звёзды так сошлись, бывает.

    Именно таким путем идет 1С. И я здесь вместе с ней, потому что мой разум не ограничен мыслями, что 1С — это только бухгалтерия.

    Вах. Прямо будто из репортажа по 1-му каналу ТВ, как флагман отечественного софта семимильными шагами опережает загнивающий Запад)))

    …наивные вы ребята. Вот пообщаетесь с реальными клиентами, вроде крупных госконтор или контор с участием гос.капитала, сра-а-азу всё поймёте. И попробуйте вякнуть, например, гендиру Росгосстраха, что 1С это не только бухгалтерия и что «разум ограничен». Ага. Вам сразу всё очень доходчиво объяснят, где Вы, где место 1С, и где место ИТ как сервисного подразделения)))

    Reply
  60. Bonov

    (63)

    И попробуйте вякнуть, например, гендиру Росгосстраха, что 1С это не только бухгалтерия и что «разум ограничен». Ага. Вам сразу всё очень доходчиво объяснят, где Вы, где место 1С, и где место ИТ как сервисного подразделения)))

    Вот тут Вы правильно заметили… В РГС ИТ именно там, где Вы думаете. А вот если взять коммерческих передовых страховщиков, то там совсем все по другому… Это по собственному опыту.

    P.S. Повторюсь: я согласен, что типовые конфы — ужасные тормоза, что БСП перегруженный монстр, но не согласен с тем, что 1С не нужно расти как учетной системе за пределами бухгалтерии.

    Reply
  61. Yashazz
    1С не нужно расти как учетной системе за пределами бухгалтерии.

    Нужно, конечно, и прекрасно, что развиваются и средства платформы, и конфигурации самого разного профиля в самых разных отраслях. Мне доводилось использовать 1С и для ВУЗовской библиотеки как документографическую ИС с хитрыми видами поиска (всё по науке))), и для чтения башорга, и для выкачивания порнухи, да простит мне Нуралиев) Я же говорю про уровень понимания «в массах» и что об него убиться можно. И говорю, что асинхронность в понимании 1С несколько странна, и что костылями попахивает. Только и всего.

    p.s. вот мне так наглядно 10 лет объясняли в таких конторах, где место 1С, что энтузиазма — ни на килобайт.

    Reply
  62. vadim1011985

    Возможно кому-то пригодится Отказ от модальности с ИТС

    Например там узнал что программа может сама переделать цепочку модальных вызовов в не модальные

    Reply
  63. herfis

    «И ты прав, и ты прав»

    Сделав ставку на УФ, 1С «просела» в части решений, где тонкий клиент не нужен. Толстый клиент жрет меньше серверных ресурсов, более отзывчив, позволяет строить более продвинутые интерфейсные решения, «моноприложение» разрабатывать проще. И далеко не всегда это перебивается плюсами тонкого клиента.

    Но выхода особого у 1С не было. Тонкие клиенты — это понятный и устойчивый тренд, а поддерживать параллельно две архитектуры — глупо по многим причинам. Но там, где тонкий клиент не нужен — да, страдает клиент 🙂

    И я больше согласен с Bonov и starik-2005 — вокруг себя я вижу все больше ситуаций, когда тонкий клиент приносит реальный профит. Да, даже в средне-больших организациях может не быть потребности в тонком клиенте. Но все чаще возникает. И да — все чаще 1С используется для сквозной автоматизации предприятия и как интеграционная платформа уровня предприятия (не в последнюю очередь благодаря тонкому клиенту). Но да, я сейчас говорю не про типовые решения…

    Да и за один только динамический интерфейс тонкому клиенту можно простить многое.

    Разработчика УФ тоже форсит на многие полезные вещи — распределение нагрузки, система доступов, минималистичный интерфейс… Убийство толстого клиента давно пора понять и простить 🙂

    БСП тоже зря тут ругаете. Не взять в самописку подсистемы управления доступом, контактной информацией, печати, РИБ (по необходимости) и еще пару-тройку полезностей — это надо быть ССЗБ.

    Reply
  64. herfis

    (66) Я всегда немодальные диалоги пишу через написание модальных с последующим авторефакторингом 🙂

    Reply
  65. vadim1011985

    (68) Век живи , век учись. Иногда просто не успеваю за всеми новшествами и узнаю о них когда они перестают быть таковыми и становятся обыденностью )))

    Reply
  66. herfis

    (69) Чтобы не пропустить ничего интересного — достаточно читать список изменений в новых релизах.

    А из рефакторинга самые полезные функции — переименование и вынос блока кода в процедуру. Это базовые возможности любых нормальных IDE, без которых жутко неудобно, если привык.

    Без легкого переименования у не тру-программера может не подняться рука на смену имени на более подходящее (тру-программеры понимают, как это важно).

    А вынос блока кода в процедуру очень хорошо подходит к стилю программирования многих (меня в том числе). Мало кто способен в голове сразу выстроить инфраструктуру будущего кода на микроуровне (понятно, что глобальные блоки продумываешь сразу). Обычно пишешь простыню и структурируешь ее по ходу. И эта возможность заметно упрощает процесс.

    Еще несколько интересных советов по настройке конфигуратора я вычитал у Хрусталевой в книжке «101 совет начинающим разработчикам» (настройка подстветки текущего идентификатора, например — нигде до этого не встречал, а ведь реально полезно).

    Reply
  67. vadim1011985

    (70) некоторые изменения я все-же читаю, но толку от этого пока не применишь на практике

    Reply
  68. Yashazz
    Да и за один только динамический интерфейс тонкому клиенту можно простить многое

    Да кому он нужен? Никто из известных мне юзеров сам себе формы не настраивал и хочет. Руководству не нравится, что каждый может настроить «в свою степь» и это не поощряется. Нафига оно?

    А вот простить конфигуратору, что управляемая форма, блин, открывается полторы минуты (на хорошем сервере) — лично я не могу. Клиент не понимает, почему время работ так выросло, и платить за тормоза конфигуратора не хочет. И скажите ещё мне, что у меня руки кривые, что я плохой танцор, и что форму документа типовой конфы без изменений в конфигураторе неправильно открываю)))

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *