<?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='\
Сходу видятся направления для улучшайзинга:
1. Запрос в цикле. Фу. Моветон. Все нужно делать в одном запросе
2. Номенклатура без характеристик. Разве в УТ 10.3 не ведется учет по характеристикам? И по сериям.
3. Разве в УТ 10.3 склад не может быть в табличной части?
Я не буду комментировать отвратительный по своей сути код с кучей ошибок, но что помешало просто добавить новую роль, в которой запрещено неоперативное проведение? Что помешало добавить одну строку в процедуру проведения Отказ = РежимПроведения = РежимПроведенияДокумента.Неоперативный;
Зачем городить этот огород? Зачем проверять остатки, если остатки проверяются по умолчанию? Зачем выполнять отмену проведения?
(2) огород городится для того, что добавление роли с запретом неоперативного проведения документа никак не поможет, в случае загрузки документов задним числом и их проведению, если отсутствуют остатки. Стандартная торговля списывает в минус склад — тут списывать в минус склад не получиться — будет запись документа.
Можешь написать более оптимизированный код — напиши здесь
Соглашусь, что косяков много. Даже слишком.
Но сказать где сделано неправильно надо.
Пропустим, что не учитываются зарезервированные товары, Допустим их нет
или что просто нужно проверять остатки .
Рассмотрим как учебный пример. Не претендую на то, что все будет правильно, но вот один из путей 🙂
1. Проверку перенести в свою подписку «Обработка проведения». Облегчит жизнь при обновлениях
2. Не получать заново объект и тем более не работать с табличной частью «товары», поскольку
количество в табличной части нужно будет приводить к единицам хранения остатков.
Под рукой нет УТ, но поскольку механизм в УТ, УПП и КА вроде одинаковый, то
таблицу можно взять
из
Движения.ТоварыНаСкладах
или
ДополнительныеСвойства.СтруктураТабличныхЧастей.ТаблицаПоТоварам.
Там таблицы уже должны быть приведены в единицам хранения.
3. Проверить опытным путем записаны ли к этому моменту движения по остаткам на складах.
Если записаны, то просто сравнить таблицу левым соединением с остатками на складе
на момент времени Новый Граница(ДатаДокумента, ВидГраницы.Включая).
Естественно связав по всем измерениям РН «Товары на складах»
Если нет, то вычесть из остатков на складе
на момент времени Новый Граница(ДатаДокумента, ВидГраницы.Исключая)
количество из полученных таблиц.
Все это можно сделать в одном запросе.
Ну какая статья такой же будет и коммент 🙂 долго оформлять после всего прочитанного
Я прочел и чуть не упал со смеху, это ужас если люди так программируют и еще выкладывают «предлагаю Вам …»!
Не нужно таких предложений.
Ошибки начинаются уже с самого названия темы: «Запрет проведения … «, а дальше видим что никакой не запрет, а контроль с непонятной отменой проведения!!!
в 1,2,4 все верно сказано.
Почти в КАЖДОЙ!!! строке ошибки логического плана:
Если Ссылка.Проведен Тогда — зачем проверка то?
ОтменаПроведения = 0; — почему Числовое, а не Булево?
ДокРеал = Ссылка.ПолучитьОбъект(); — зачем получать объект?
Для Каждого Стр ИЗ ТоварыДокумента Цикл — почему без запроса?
КоличествоНоменлатурыНаСкладе = ПоискОстатковПоСкладу(Стр.Номенклатура, ДокРеал.Дата, ДокРеал.Склад); — это вообще УЖОС 8-( как можно крутить в цикле запрос и при этом выкладывать как рабочее решение? крутите себе на здоровье, только не учите этому никого иначе у вас клиентов заберут или с работы попрут
СколькоНехватает = КоличествоНоменлатурыНаСкладе — Стр.Количество; — зачем в 2 строки? когда переменная КоличествоНоменлатурыНаСкладе используется 1 раз?
ОбработкаУдаленияПроведения(Отказ); — это вообще не нужно если проверка делается до!!! проведения я уж не говорю что «ищем процедуру «ОбработкаПроведения» » вообще не нужно делать, проверки все делаются ПередЗаписью, иначе у вас 10 000 доков будут проводится не 1 минуту, а целый час а то и день.
ДокРеал.Записать(РежимЗаписиДокумента.ОтменаПроведения); — от этого бы я упал если бы не сидел на стуле
Сообщить(«Отмена проведения документа «+ДокРеал+ Символы.ПС); — тут все становится ясно про уроень программирования — ПС в конце это для чего?
В общем ошибок нет только в написании операторов, в остальном просьба все НИКТО НЕ ДЕЛАЙТЕ НИЧЕГО ПОДОБНОГО
если не умеете программировать и логически мыслить лучше не показывайте этого, в идеале лучше вообще не занимайтесь этим, но идеал вряд ли достжим.
Вот из-за таких нас 1С-ков и считают недопрограммистами.
Если СколькоНехватает < 0 Тогда
Нужно 1 шт, на складе 1 шт.
СколькоНехватает = 1 — 1 = 0 и далее по условию
И это помимо всего выше сказанного….
Соглашусь, что код ужасен.
Если очень хочется проверять остатки (Хотя зачем их проверять при неоперативном проведении? Уже сотни копий сломаны об этот вопрос), не проще включить этот самый контроль остатков в самой УТ? Там ведь так и написано «Если Неоперативно, то НеПроверяем»..
Слишком много вылили на парня…))
Код действительно можно много где улучшить.. Но я так понимаю ты для этого и написал — чтобы тебе подсказали «где и как».
Пиши дальше.. учись и если получиться сделай вывод — лучше одно классное решение чем 10 сделанных поспешно или непроверенных.
В модуле объекта тебе доступен сам объект так что Ссылка.Проведен не надо делать.. это вызовет излишнее обращение к СУБД.
К объекту обратись через ЭтотОбъект.. не нужно его получить заново — это затратная операция.
(3) Исправлении Реализации задним числом легко образуются МИНУСА по другим документам (позже по Периоду)…
Если правка задним числом нужна ля исправления ошибок учета…то в таком случае часто приходится править сразу несколько документов… И единственный корректный контроль возможен только за Оперативным остатком! Причем контроль надо производить о ВСМ измерениям Регистра! При обнаружении Оперативных Минусов — Предупреждать (а может и запрещать некоторым некоторые документы проводить) !
А я не верю, что автор серьёзно. По-моему, он просто тролль: «А напишу-ка я адову жесть и посмотрю, как остальные срач устроят».