Собственный алгоритм нумерации документов определенного вида




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

11 Comments

  1. tusv

    Что то много лишних букв

    В Запросе Вторую временную таблицу зачем? Когда Можно сгруппировать и по Ссылка, вместо НомерСтроки.

    Да и можно сразу

    ВЫБРАТЬ
    1  КАК НомерСтроки,
    Максимум(РеализацияТоваровУслуг.Номер) КАК Строка
    ПОМЕСТИТЬ Дано
    ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
    ГДЕ
    РеализацияТоваровУслуг.Дата Между &Дата1 и  &Дата2
    

    Показать

    Зачем выводить лидирующие нули циклом когда можно форматом

    НовыйНомер = Префикс+Формат(НомерЧисло+1, «ЧЦ=»+ДлинаНомераБезПрефикса+»; ЧВН=; ЧГ=»);
    
    Reply
  2. xan333

    (1)


    1. tusv 26 11.04.19 15:59

    Что то много лишних букв

    В Запросе Вторую временную таблицу зачем? Когда Можно сгруппировать и по Ссылка, вместо НомерСтроки.

    Да и можно сразу

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

    Reply
  3. tusv

    (3)

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

    Вы нумеруете строки для того, чтобы Сгруппировать по номеру строки. Совершенно лишняя операция. Сгруппируйте по ссылке. То же самое, только быстрее на 30%

    ВЫБРАТЬ ПЕРВЫЕ 30
    РеализацияТоваровУслуг.Номер КАК Номер,
    РеализацияТоваровУслуг.Ссылка КАК Ссылка
    ПОМЕСТИТЬ Данные
    ИЗ
    Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
    
    УПОРЯДОЧИТЬ ПО
    РеализацияТоваровУслуг.Дата УБЫВ
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ ПЕРВЫЕ 1
    СУММА(А.П * Б.С) / МИНИМУМ(А.П) КАК Ответ
    ИЗ
    Р16 КАК А,
    Р16 КАК Б,
    Данные КАК Данные
    ГДЕ
    Б.С < 10
    И ПОДСТРОКА(Данные.Номер, 17 — А.С, 1) = ПОДСТРОКА(«0123456789», Б.С + 1, 1)
    
    СГРУППИРОВАТЬ ПО
    Данные.Ссылка
    
    УПОРЯДОЧИТЬ ПО
    Ответ УБЫВ

    Показать

    Reply
  4. Oldsad

    (2)

    К сожалению очень много подобных костылей работает в реальных базах и

    свою задачу выполняет

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

    Вы же выложили ЭТО на инфостарте

    Единственная ценность ЭТОГО, это запрос, в котором строки преобразуются в числа,

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

    П.С. Данный код в общем случае не решает поставленную задачу

    Reply
  5. xan333
    Reply
  6. xan333

    (5)Вы видимо до сих пор отлаживаете свои разработки, если ни одной публикации у вас нет на Инфостарте. Видимо стремитесь к идеалу. Код решает задачу. Это не голая теория, он работает в реальной рабочей базе Бухгалтерия3.

    Reply
  7. xan333

    (6)Ваш вариант работает, разобрался почему были разные результаты. У вас сортировка в первом запросе по Дате, а у меня по МоментВремени. Верный номер на моих данных определялся по МоментВремени.

    Reply
  8. Oldsad

    (7)

    от того что код работает в реальной базе, лучше он не становится

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

    во вторых, попробуйте создать один документ, записать его к примеру вначале года (перед этим не забудьте сделать тысячу документов из предыдущего пункта), затем создать еще один документ и записать

    и это только вопросы к работоспособности

    про такие мелочи как автонумерация в запросе я вообще молчу, т.к. там нумерация как пятая нога собаке

    Reply
  9. tusv

    (6)(8)

    Вы моделировали ситуацию в своей базе? С номером документа включающим «/»?

    Да моделировал в Демо торговле. В диаграмме Ваш запрос со второй таблицей и без нее. И оба не работают, ибо возвращается максимальный номер первых 30 — последних документов без учета Организаций

    У вас сортировка в первом запросе по Дате, а у меня по МоментВремени. Верный номер на моих данных определялся по МоментВремени.

    У меня в примере не правильно. Что такое МоментВремени. Это составное не индексированное поле из Дата и Ссылка. Потому его не рекомендуют использовать. Правильней сортировать по Дата убыв, Ссылка убыв

    Reply
  10. xan333

    (10) У меня база Бухгалтерия 3 и одна организация, для случая нескольких Организаций возможно последний номер получается не верно

    Reply
  11. xan333

    (9)В моем конкретном случае нет такого объемного документооборота, не более тысячи документов в год, бухгалтера довольны что им не приходится номер руками перебивать. В любой момент простым изменением значения константы я могу отключить эту нестандартную нумерацию.

    Reply

Leave a Comment

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