Запрет проведения документов в неоперативном режиме УТ 10.3




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

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

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

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

10 Comments

  1. Hitcher

    Сходу видятся направления для улучшайзинга:

    1. Запрос в цикле. Фу. Моветон. Все нужно делать в одном запросе

    2. Номенклатура без характеристик. Разве в УТ 10.3 не ведется учет по характеристикам? И по сериям.

    3. Разве в УТ 10.3 склад не может быть в табличной части?

    Reply
  2. slazzy

    Я не буду комментировать отвратительный по своей сути код с кучей ошибок, но что помешало просто добавить новую роль, в которой запрещено неоперативное проведение? Что помешало добавить одну строку в процедуру проведения Отказ = РежимПроведения = РежимПроведенияДокумента.Неоперативный;

    Зачем городить этот огород? Зачем проверять остатки, если остатки проверяются по умолчанию? Зачем выполнять отмену проведения?

    Reply
  3. aximo

    (2) огород городится для того, что добавление роли с запретом неоперативного проведения документа никак не поможет, в случае загрузки документов задним числом и их проведению, если отсутствуют остатки. Стандартная торговля списывает в минус склад — тут списывать в минус склад не получиться — будет запись документа.

    Можешь написать более оптимизированный код — напиши здесь

    Reply
  4. Hitcher

    Соглашусь, что косяков много. Даже слишком.

    Но сказать где сделано неправильно надо.

    Пропустим, что не учитываются зарезервированные товары, Допустим их нет

    или что просто нужно проверять остатки .

    Рассмотрим как учебный пример. Не претендую на то, что все будет правильно, но вот один из путей 🙂

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

    2. Не получать заново объект и тем более не работать с табличной частью «товары», поскольку

    количество в табличной части нужно будет приводить к единицам хранения остатков.

    Под рукой нет УТ, но поскольку механизм в УТ, УПП и КА вроде одинаковый, то

    таблицу можно взять

    из

    Движения.ТоварыНаСкладах

    или

    ДополнительныеСвойства.СтруктураТабличныхЧастей.ТаблицаПоТоварам.

    Там таблицы уже должны быть приведены в единицам хранения.

    3. Проверить опытным путем записаны ли к этому моменту движения по остаткам на складах.

    Если записаны, то просто сравнить таблицу левым соединением с остатками на складе

    на момент времени Новый Граница(ДатаДокумента, ВидГраницы.Включая).

    Естественно связав по всем измерениям РН «Товары на складах»

    Если нет, то вычесть из остатков на складе

    на момент времени Новый Граница(ДатаДокумента, ВидГраницы.Исключая)

    количество из полученных таблиц.

    Все это можно сделать в одном запросе.

    Reply
  5. CaSH_2004

    Ну какая статья такой же будет и коммент 🙂 долго оформлять после всего прочитанного

    Я прочел и чуть не упал со смеху, это ужас если люди так программируют и еще выкладывают «предлагаю Вам …»!

    Не нужно таких предложений.

    Ошибки начинаются уже с самого названия темы: «Запрет проведения … «, а дальше видим что никакой не запрет, а контроль с непонятной отменой проведения!!!

    в 1,2,4 все верно сказано.

    Почти в КАЖДОЙ!!! строке ошибки логического плана:

    Если Ссылка.Проведен Тогда — зачем проверка то?

    ОтменаПроведения = 0; — почему Числовое, а не Булево?

    ДокРеал = Ссылка.ПолучитьОбъект(); — зачем получать объект?

    Для Каждого Стр ИЗ ТоварыДокумента Цикл — почему без запроса?

    КоличествоНоменлатурыНаСкладе = ПоискОстатковПоСкладу(Стр.Номенклатура, ДокРеал.Дата, ДокРеал.Склад); — это вообще УЖОС 8-( как можно крутить в цикле запрос и при этом выкладывать как рабочее решение? крутите себе на здоровье, только не учите этому никого иначе у вас клиентов заберут или с работы попрут

    СколькоНехватает = КоличествоНоменлатурыНаСкладе — Стр.Количество; — зачем в 2 строки? когда переменная КоличествоНоменлатурыНаСкладе используется 1 раз?

    ОбработкаУдаленияПроведения(Отказ); — это вообще не нужно если проверка делается до!!! проведения я уж не говорю что «ищем процедуру «ОбработкаПроведения» » вообще не нужно делать, проверки все делаются ПередЗаписью, иначе у вас 10 000 доков будут проводится не 1 минуту, а целый час а то и день.

    ДокРеал.Записать(РежимЗаписиДокумента.ОтменаПроведения); — от этого бы я упал если бы не сидел на стуле

    Сообщить(«Отмена проведения документа «+ДокРеал+ Символы.ПС); — тут все становится ясно про уроень программирования — ПС в конце это для чего?

    В общем ошибок нет только в написании операторов, в остальном просьба все НИКТО НЕ ДЕЛАЙТЕ НИЧЕГО ПОДОБНОГО

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

    Вот из-за таких нас 1С-ков и считают недопрограммистами.

    Reply
  6. evillit
    СколькоНехватает = КоличествоНоменлатурыНаСкладе — Стр.Количество;

    Если СколькоНехватает < 0 Тогда

    Нужно 1 шт, на складе 1 шт.

    СколькоНехватает = 1 — 1 = 0 и далее по условию

    И это помимо всего выше сказанного….

    Reply
  7. flu

    Соглашусь, что код ужасен.

    Если очень хочется проверять остатки (Хотя зачем их проверять при неоперативном проведении? Уже сотни копий сломаны об этот вопрос), не проще включить этот самый контроль остатков в самой УТ? Там ведь так и написано «Если Неоперативно, то НеПроверяем»..

    Reply
  8. danila_inf

    Слишком много вылили на парня…))

    Код действительно можно много где улучшить.. Но я так понимаю ты для этого и написал — чтобы тебе подсказали «где и как».

    Пиши дальше.. учись и если получиться сделай вывод — лучше одно классное решение чем 10 сделанных поспешно или непроверенных.

    В модуле объекта тебе доступен сам объект так что Ссылка.Проведен не надо делать.. это вызовет излишнее обращение к СУБД.

    К объекту обратись через ЭтотОбъект.. не нужно его получить заново — это затратная операция.

    Reply
  9. V.Nikonov

    (3) Исправлении Реализации задним числом легко образуются МИНУСА по другим документам (позже по Периоду)…

    Если правка задним числом нужна ля исправления ошибок учета…то в таком случае часто приходится править сразу несколько документов… И единственный корректный контроль возможен только за Оперативным остатком! Причем контроль надо производить о ВСМ измерениям Регистра! При обнаружении Оперативных Минусов — Предупреждать (а может и запрещать некоторым некоторые документы проводить) !

    Reply
  10. vasyak319

    А я не верю, что автор серьёзно. По-моему, он просто тролль: «А напишу-ка я адову жесть и посмотрю, как остальные срач устроят».

    Reply

Leave a Comment

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