Коррекция регистров




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

40 Comments

  1. vet7777

    вот собственно и мой подарок вам….

    Reply
  2. seermak

    Интересно,я не до конца разобрался пока. Вопрос:

    Процедура ОбработкаПроведения()

    СпрТов=Создатьобъект(«Справочник.Номенклатура»);

    СпрТов.ВыбратьЭлементы();

    Пока СпрТов.ПолучитьЭлемент()=1 Цикл

    Если СпрТов.ЭтоГруппа()=0 Тогда

    Значение=СпрТов.ТекущийЭлемент();

    Прервать;

    КонецЕсли;

    КонецЦикла;

    этот кусок кода для чего?

    Reply
  3. vet7777

    сам не помню уже 🙂 давно писал….

    спасибо за находку, поправлю.

    Reply
  4. vet7777

    новая версия 1.1

    — удалил лишнее, подравнял, запеременил процедуры и функции…

    — добавил возможность вводить сторно на основании другой коррекции или любого документа (нужнот только установить возможность вводить на его основании)

    Reply
  5. CheBurator

    Заголовки измерений меняются после выбора вида регистра?

    Reply
  6. poppy

    КолИзм = Метаданные.Регистр(ПечРегистр).Измерение();

    {Документ.КоррекцияРегистров.Форма.Модуль(732)}: Поле агрегатного объекта не обнаружено (Измерение)

    Reply
  7. CheBurator

    (6) в качестве ПечРеггистр передан идентификатор несуществующего регистра…??

    Reply
  8. poppy

    (7) Точно, в конфигурации где регистров нету совсем… 😉

    Reply
  9. CheBurator

    Ура! я выиграл пирожок! просто тольо потому, что получил аналогичную ошибку при обрашении к Ревизит(ИмяРеквизита).Длина — имяреквизита было «неправильное»

    Reply
  10. poppy

    У меня в аналогичной разработке стоит запрет на создание документа при отсутствии регистров.

    Reply
  11. vasilykushnir

    (7) Или я чего-то не понял, или… тяжелое последствие праздников… Обработка «Коррекция регистров». А что корректировать, если регистров нет…?

    А вообще спасибо автору — давно ожидаемая обработка.

    Reply
  12. vet7777

    сделать чтобы при открытии посылала в сад, когда нет регистров? :)))))

    Reply
  13. poppy

    (12)Напиши например так:

    В процедуре ПриОткрытии()

    Код
       Если ВидРегистра.РазмерСписка()>0 Тогда
          Если ВидРегистра.ТекущаяСтрока()=0 Тогда
             ВидРегистра.ТекущаяСтрока(1);
          КонецЕсли;
       Иначе
          Сообщить("В данной конфигурации нет ни одного регистра!");
          СтатусВозврата(0);
       КонецЕсли;
    

    Показать полностью

    Посмотри как у меня сделано в идентичном документе http://infostart.ru/projects/888/

    Reply
  14. vasilykushnir

    (12) +5

    — Папа, откуда берутся дети?

    — Оттуда, куда потом посылают взрослых…..

    Reply
  15. vet7777

    так что? дальше открытия документа кто-нибудь ходил? 🙂

    какие еще есть пожелания, замечания?

    Reply
  16. seermak

    я включил в рабочую конфу, но пока «оказии» для применения небыло. Надеюсь что в нужный момент не подведет;)

    Reply
  17. poppy

    (15)

    Есть еще фича. В оборотных регистрах движение не завист от знака, указанного в документе.

    Reply
  18. Ёпрст

    (18) а должно? :)))))

    Reply
  19. Dolly_EV

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

    ( Reply

  • poppy

    (19) Конечно смотри http://infostart.ru/projects/888/

    Вот еще похожий документ http://infostart.ru/projects/2172/ не мое.

    (18)

    Нет, недолжно. Здесь для создания движений оборотных регистров вместо метода ДвижениеВыполнить() используются методы ДвижениеПриходВыполнить() и ДвижениеРасходВыполнить(). Вроде все работает, но в этом есть некоторая неаккуратность…

    Reply
  • Ёпрст

    (20) Ну, раз создатели не озаботились правильной работой методов то и ладно.. 🙂

    Это как получение атрибутов ДатаДок и НомерДок у документа двигающего регистр в запросе… Тоже по-разному «работает» в скули и дбф, хотя не должно работать вообще…

    Reply
  • seermak

    А и правда: методы для регистров оборотов и остатков разные…….

    Reply
  • Dolly_EV

    (20) ето я все видел.

    Reply
  • Dolly_EV

    Вобщем — весчь! Автору — респект!.. добавил еще фильтр «В» для измерений (тип «Справочник») и ПОООЛностью удовлетворился!

    жаль, только 1 плюс ставится.

    Reply
  • Ёпрст

    Аналогичная ошибка и в этой обработке при работе с метаданными….

    Точнее недочОт и еще какой…

    Хорошие грабли для начинающих 🙂

    Reply
  • vovk_v

    Владислав, спасибо! Работает на твердое 5! +1 🙂 Отдельная благодарность за то, что поделились разработкой, ведь теперь мы можем сосредоточиться на решении других задач, а не решать каждый по отдельности одно и то же 1000 раз. 😉

    Reply
  • vet7777

    (24,26) Очень рад что разработка понравилась и пригодилась!

    Сам пользовался и редактором реквизитов и коррекцией регистров довольно долго, инструменты получились очень хорошие, много раз выручали…

    To Dolly_EV: В следующую версию добавлю фильтр «В» для измерений. 🙂

    На базе этой коррекции можно решить проблему свертки, только нужно сделать или найти обработки — выгрузка документов в файл, загрузка документов из файла, ну и обработку свертки написать, которая создаст по всем регистрам остатков документы коррекции пачками (с учетом ограничения строк в документе) …

    Наработки такие были, найду — выложу…

    А так вообще, чем вам не редактор движений? )

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

    Reply
  • Ёпрст

    (27) как на счет (25) ?

    Reply
  • vet7777

    (28) в 25 ничего конкретно не написано, может в 6?

    Reply
  • Ёпрст

    (29) а ну да, забыл сказать, просто в другой ветке говорил… 🙂

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

    Все как-то про них забывают. Потом граблёй по лбу имеют… Особенно при свёртке.

    Reply
  • vasilykushnir

    (30) А если для неопределенного предложить юзьверу выбрать тип метаданного, а потом уже по назначенному типу — выбор самого матаданного? Кстати, ты прав, этим грешат даже очень солидные проекты — сколько раз предлагал Доржи сделать подобный выбор в Новейшем Отчете, цены б ему тогда не было…. Хотя он и так в ракламе не нуждается — функционал выше крыши.

    А вот эти две обработочки Влада — текущая и редактор реквизитов — не смотря на мелкие шероховатости — просто прелесть. Правда Редактор реквизитов я дополнил перепроведением дока — честно! влом мне создавать еще один корректирующий документ. Знаю, знаю, что это есть неверный подход, но… Да и сами данные меняю только те, что не влияют на товарные отчеты и в документах, любое действие над которыми уже запрещено — доки у меня могут корректироватся только не более 3-х дневной давности — более поздние уже фиг (только обработочка Влада и выручает).

    Reply
  • Ёпрст

    (31) Зачем юзверю это надо ? :))

    Всё гораздо проще :

    При записи атрибутов , просто поглядеть на тип реквизита/измерения (смотря, куда пишем) из самих метаданных, если неопределенно и значение записываемого атрибута не пустое — назначаем тип реквизиту/измерению, беря его из самого значения атрибута.. Вот и всё. Т.е. тупо вставить условие на неопределенный тип.

    Пара строк кода.

    🙂

    Reply
  • Ёпрст

    +32 А вид, как мы знаем, назначать необязательно, главное ТИП …

    Reply
  • vasilykushnir

    (33) В принципе таки да — можно и так. Это даже попроще.

    Reply
  • vasilykushnir

    + к (34) А под юзьвером я предполагал человека работающего с обработкой и это далеко не рядовой юз.

    Reply
  • Dolly_EV

    помимо «В» еще ошибочка (или недоЧОТ)):

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

    Reply
  • karat60

    +1, нужная весчь

    Reply
  • quick

    +1, однозначно нужная 😎

    Reply
  • makaray

    я хоть и занимаюсь 1С не очень давно, но уже реально оценил, вещчь!

    Reply
  • vlanik

    Задумка хорошая, с недочетами можно справиться и самому, а так вещь полезная.

    Reply
  • Leave a Comment

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