Метод формирования движений в типовых регистрах нетиповыми регистраторами




Принцип обмена данными из 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='\

34 Comments

  1. acsent

    отчеты с разворотом до регистратора будут совсем не удобны

    Reply
  2. itriot11

    (1) ну это же можно решить сделав небольшой допил необходимых отчетов.

    Reply
  3. aka Любитель XML

    В целом не плохо, плюсанул, возможно прикручу где-нибудь

    Reply
  4. nomadon

    А где упоминание об обработке представления корркктировки?

    Reply
  5. itriot11

    (4) Добавлю чуть позже, спасибо.

    Reply
  6. nomadon

    (1) с помощью (4) решается) делается обработка представления, и подменяется открываемая форма корректировки

    Reply
  7. itriot11

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

    Reply
  8. Bazil

    Решение оригинальное. Но мне кажется, задача «не затереть тип регистратора в регистре» не такая сложная. Простые тесты, памятка для обновляльщика легко её решают. Решая несложную задачу, вы порождаете большее количество сложностей. Вроде как облегчилось обновление, но для работы расшифровок по регистраторам надо будет переписать кучу типовых отчетов, а это приводит наоборот, к усложнению (я в курсе про переопределение представления, но оно возможно только на 8.3 без режима совместимости с 8.2). А еще, например, есть обработки, которые дописывают движения в существующие документы, типа восстановление расчетов, и их тоже придется пилить.

    Reply
  9. itriot11

    (8)

    Вопрос сложности имеет место быть. Каким образом я для себя принял решение в рамках задачи приведенной в примере:

    — уже имею готовый алгоритм обхода модификации регистра

    — не горю желанием помнить лишний раз про типы регистраторов

    — меня тревожит вероятность допустить ошибку при обновлении(не смотря на тесты и бэкапы)

    — пользователи допускают в отчетах видеть в качестве регистраторов таких движений документ «Корректировка записей регистров».

    — пользователей желающих видеть в качестве представления исходный документ не нашлось

    — специфические обработки не используется

    Вангую, если бы возникли пользователи захотевшие увидеть исходный документ, то речь шла об 1-2 формах отчетов/списков, а не о куче, и считаю, что это для меня было бы не трудно реализовать.

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

    Reply
  10. u_n_k_n_o_w_n

    (9) , тесты как раз и решают Вашу головную боль. В приведенном примере как раз «ярко» описывается пример, когда «вроде бы» не надо даже тестировать конфигурацию.

    Reply
  11. u_n_k_n_o_w_n

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

    Reply
  12. itriot11

    (11) расскажите свой опыт и цели?

    Reply
  13. ILM

    А зачем у вас «Инвентаризация тары» делает движения? Инвентаризация — это фиксация наличия/отсутствия ТМЦ на заданный момент времени.

    Reply
  14. itriot11

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

    Reply
  15. lunjio

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

    (8)

    Reply
  16. itriot11

    (15)

    с учетом того, что это будет работать на 8.3

    Кажется, именно об этом я написал в последнем пункте в кате P.S.S.)

    На всякий случай — при нажатии он раскроется и покажет текст с примером кода.

    Reply
  17. u_n_k_n_o_w_n

    (11), не хотелось править движения документа Сторно.

    Reply
  18. kote

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

    Она должна проверять наличие в нужных реквизитах нужных типов и сигнализировать об отклонениях.

    Пишется один раз и далее не дает забыть об изменениях.

    Reply
  19. itriot11

    (18)

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

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

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

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

    Reply
  20. kote

    (19)

    Когда Вы изменяете конфигурацию — вы, как правило, в эти реквизиты добавляете свои типы (и, возможно, убираете/подменяте конкретные типы поставщика)

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

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

    Это хорошая практика.

    Reply
  21. itriot11

    (20) а, обработка контролит только наличие собственных типов. Такое реализовать можно и достаточно легко. Конечно, еще одна проверка позволяет снизить вероятность допущения ошибки. Но обработка запуститься уже после случившегося. Ок, если накосячил специалист обновляющий базу, то пусть берет бэкап и делает все заново, без ошибок. Однако, на сколько это решение подходит к контексту приведенному мной в предыдущем сообщении? Описанный мною подход вообще полностью исключает возможность потерять данные.

    Reply
  22. kote

    А разве кто-то обновляет доработанные конфигурации на рабочей базе??

    Это очень глупо. Правильно это делается так: выгрузите cf, загоните в пустую базу, обновите, проверьте (той самой обработкой), потом объедините рабочую с cf из обновленной конфигурации..

    Reply
  23. itriot11

    (22)Вы упрямо не обращаете внимание на написанное мною ранее) Всего хорошего.

    Reply
  24. sashocq

    Собственно, непонятно, зачем так делать.

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

    — добавление/изменение типа какого-то реквизита

    — добавление/удаление реквизита объекта

    — изменение прав ролей

    и ещё кучу всего.

    Другими словами, от ошибок при обновлении это никак не спасёт, но сложности прибавит существенно.

    Reply
  25. itriot11

    (24)

    от ошибок при обновлении это никак не спасёт, но сложности прибавит существенно.

    расскажите об ошибках при обновлении, когда будет применен описанный мною механизм?

    Reply
  26. sashocq

    (25) Я уже написал в (24) :

    Если в реквизите с множественным типом (например, ДокументОснование) вы добавили свой тип добавленного документа, потом при обновлении поставщик меняет тип реквизита (добавляет свой), то при обновлении тип реквизита может замениться, ваш добавленный слетит и все такие значения в базе превратятся в Неопределено (реальный пример из рабочей базы).

    Похожая ситуация может быть с составом плана обмена. Вообще с любым объектом метаданных, ссылающимся на коллекцию других метаданных.

    Reply
  27. itriot11

    (26) А как это связано с тем о чем я писал в публикации?) Вы ее читали? Я не меняю типы данных, как раз об избежании этого пишу. Вообще исключаю проблему описанную вами.

    Reply
  28. strange2007

    (8) Всегда прихожу в конторы, где уже никто ничего не может обновить без потерь. Уверяю, все эти доработки состоят из вот таких вот мелких: «ну а чо там обновлять то? Одна галочка же». А по факту хоть засравнивайся, всё равно всё разваливается нафиг. Вот и переделываю на такие же механизмы, как указаны у автора. Уже очень много лет

    Reply
  29. strange2007

    Автор, не слушайте противников таких методов. Они просто ещё не прочувствовали вкус изолированных механизмов. Особенно когда вместо недели на обновление уходит 5 часов (скачать, обновить 3 базы, провести поверхностное тестирование).

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

    1. Всё в отдельной подсистеме. Всё только на подписках.

    2. Дополнительные отчёты и обработки.

    3. Методологическая фигня.

    Есть ещё проблема создания реквизитов на форме, но для УПП 1.3 смог всё решить при помощи этих 3-х пунктов

    Всё. Ни одного предприятия ещё не находил, где бы пришлось менять конфигурацию.

    Удачи, автор, в этой прикольной тематике.

    Reply
  30. itriot11

    (29) со вторым пунктом ай-яй как не согласен. Категорически стараюсь не использовать внешние отчеты и обработки. Есть серьезная вероятность испортить их работоспособность, если модифицировать объекты или фрагменты кода конфигурации связанные с ними. Ни система, ни разработчик просто не увидят, что изменения затронут внешние объекты. Вероятность порчи внешних отчетов и обработок возрастает, если они не зарегистрированы в справочнике, а находятся в каталогах(рабочих столах) пользователей. А если еще попасть в момент смены разработчика, допустим прийти на новое место, где некому передать дела? Можно сильно напартачить. А то что внешние отчеты или обработки будут включены в состав конфигурации — так это, на мой взгляд, мелочь, тут сложно ошибиться.

    Отдельное спасибо за поддержку)

    Reply
  31. strange2007

    (30) Недавно делал механизм крутейших скидок для УТ10. Один справочник с настройками (в отдельной подсистеме) и одна внешняя обработка табличных частей для документов по продаже. Даже если всю конфигурацию переменяют, то эта связка окажется не тронутой.

    В описанном механизме реализованы варианты всяких скидок по самым невообразимым условиям. Вместо меня за УТху сел другой человек. Через короткое время начал пользоваться этим инструментом и теперь его ни на что не хочет менять.

    Единственное с чем сталкиваемся, так это когда обновляем платформу. Надо все отчёты и обработки переоткрывать в конфигураторе. Но это по правде мелочи по сравнению с необновляемыми конфигурациями

    Reply
  32. the1

    (31) Если уж в конфигурацию добавлен свой СПРАВОЧНИК, то не вижу никакого смысла прятать еще что-то во внешние обработки, сложность обновления от этого не изменится ни на йоту. Как вариант, добавили бы произвольную форму этого справочника и творили бы там что угодно, как в обработке.

    Reply
  33. strange2007

    (32) точно так и есть, за исключением одного но (!!!!!) — каким образом поместить мордочку на кнопку ТЧ? Поэтому я принял решение использовать механизмы БСП, т.е. внешняя обработка.

    Reply
  34. the1

    (33) ну да, логично)

    Reply

Leave a Comment

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