<?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='\
Спасибо за статью. Мне тоже довелось с этой ошибкой столкнуться, теперь уже стало понятнее, в чем проблема
(1) Да, я помню, что сильно удивился первый раз, когда мне пользователи на эту ошибку указали. Пришлось разбираться, т.к. уже было штук 30 различных сохраненных пользовательских настроек — не писать же на каждую свой отчет… 😉
Заодно вспомнил, что у меня есть материал для еще одной заметочки на тему универсального отчета, на днях напишу и выложу.
«Мне удалось найти одно ограничение, связанное с этим решением»
попробуй установить флаг у поля «регистратор» — обязательное.
(3) Я думал об этом, но не пробовал. Мне кажется, это не совсем верное решение проблемы, т.к. регистратор далеко не всегда вообще нужно выводить в отчет (как и детальные записи в принципе). Что будет выведено в отчет, если в настройках флажок «Детальные записи» снят, а поле Регистратор помечено в СКД как обязательное? Не знаю, надо будет попробовать.
(3) Попробовал сделать Регистратор обязательным полем. Сразу же полезли ошибки СКД из-за последовательности нумерации периодов. Никому этот вариант не рекомендую, не зря он казался мне подозрительным. 😉 Лучше уж оставить все в исходном варианте, как в статье.
(5) Да, про обязательное поле брякнул не то. Сейчас посмотрю….
На каких релизах проверяли?
(7) На Бух 1.6.22.4 и ранее.
В УПП та же картина на нескольких релизах (точнее, на всех, виденных мной), точно номера не помню.
Только что проверил на платформе 8.2.10.73 в той же Бух 1.6.22.4 — глючит все так же.
В стандартных отчетах 1С:Торговли при выводе детальных записей по регистратору необходимо добавлять также поле Период для правильного расчета группировок и остатков (Период+Документ движения (регистратор)). Видимо здесь такая же ситуация.
(9) Попробовал добавить к регистратору еще поле «Период секунда» — не помогает, как и добавление любого другого поля. Ошибка остается. Стандартные отчеты УТ, очевидно, реализованы несколько иначе (скорее всего, при их создании все же использовался конструктор СКД).
Больше всего напрягает тот факт, что создаваемые самой платформой при инициализации компоновщика настроек служебные поля «Регистратор» («Recorder») и «номер строки» потом никак нельзя изменять — к ним не удается обратиться как к обычному полю набора данных СКД.
Я надеялся, что в новых версиях платформы что-нибудь изменится, но уже 8.2.10 вышла, а воз и ныне там.
У меня есть похожий отчет, только на основе универсального отчета, по регистрам партий (комплексная конфигурация, УПП). Проблема с выводом начальных остатков и расшифровок по документам. При выводе расшифровки строки в режиме период+регистратор и отключения детальных записей — все получается (проверено) кроме начальных остатков. Кто-нибудь поможет решать эту проблему?
Недавно мне понадобилась эта статья, когда мы стали пытаться анализировать полученную из другой базы через COM-соединение таблицу остатков и оборотов с детальными записями. В исходной базе остатки считались корректно, но после выгрузки результата запроса в таблицу значений и обработки этой таблицы в другой БД настройки пришлось прописывать вручную — тут и вспомнилось про эту статью.
Выяснилось, что если содержимое строки таблицы значений содержит движения накопления по ресурсам вида «нач.остаток/приход/расход/кон.остаток», то для корректного расчета остатков по группировкам средствами СКД необходимо выполнить настройки, аналогичные описываемым в статье.
В исходной таблице значений обязательно должно быть поле периода (дата движения или период из р/н). Если его там нет — добавляем. Затем в настройках СКД нужно присвоить этому полю роль «Период, 1», и далее заполнить роли для полей остатков и измерений, как описано в статье.
При этом желательно все измерения сделать обязательными, а поля необязательных измерений убрать вообще, т.к. группировка по «необязательным» измерениям мешает корректному расчету остатков.
Конечно, результат получится далеко не столь гибким, как мы привыкли видеть в отчетах на СКД. Но он хотя бы будет верным!
Отличная статья, очень полезные комментарии, хорошо её дополняющие. Спасибо.
(15) Boroda, спасибо за столь положительный отзыв!
Как раз после того, как написал последний комментарий, я еще раз все перечитал и решил полностью переработать текст статьи.
Теперь статья не только про универсальный отчет, которым далеко не все пользуются, но главным образом про нюансы настройки СКД.
Я не претендую на особое знание глубинных механизмов СКД, но делюсь тем, что удалось накопать мне самому и вместе с коллегами.
(13) e.kogan, в статье сразу предлагается прописать роли для полей остатков с помощью типовой процедуры общего модуля. 😉
Т.е. вашу конструкцию вида
можно заменить на:
По моему опыту, этого будет вполне достаточно.
Хотя и ваш вариант, конечно, тоже будет работать.
P.S. Все обсуждаемые изменения касаются процедуры ДобавитьПоляНабораДанных() модуля объекта УниверсальныйОтчетПоМетаданным.
Все желающие «починить» универсальный отчет могут заменить код этой процедуры на код, приведенный e.kogan в (13).
на мисте есть обсуждение этой темы… ссылку, к сожалению, не дам… гуглите
на ИТС есть статья, полностью и на примерах раскрывающая тему ролей в СКД. В указанном обсуждении на мисте есть ссылки на скрины статьи ИТС 🙂
что интересно, в обычных запросах с итогами остатки считаются верно самой 1С на уровне платформы. И вот эту «верность» срубить весьма непросто.. )) Даже при скидывании выборки во временную таблицу 1С всё равно «помнит» остаточные поля и верно считает остатки (т.е. арифметически — неверно). Отбить память об остатках получается только при втором или третьем перескидывании во временную таблицу…
а в СКД получается, наоборот, механизмы запросных итогов они видимо отключили, как и сами итоги, поэтому приходится принудительно распределять роли полей для корректного расчета остатков.
(18) romansun, спасибо за наводку, надо будет поискать 🙂
Только статья-то исходно была написана 2 года назад, когда еще никакой информации толком не было…
UPD: вот, нашел на мисте кое-что с ИТС:статья «Типичные проблемы при расчете остатков»
(17) это хорошо, когда конфигурация типовая 🙂
(20) e.kogan, ну у вас в коде тоже без вызова типовых функций все того же общего модуля не обошлось ))
(21) Гм, оно у меня переопределяется 🙂 На самом деле это форма с экспортными процедурами 🙂 самый простой способ выдрать всё на свете из конфы.
*упс, дважды отправилось
(19)
дадада.. 🙂 она самая
и что меня убивает лично во всей этой ситуации — что такая, действительно, важная вещь, как «Роли» в библии СКД от Хрусталёвой (библии, ибо больше нигде консолидированно инфы по СКД толком нет) описана в виде одной странички с общим смыслом: «а еще в СКД есть роли, они нужны… нужны, т.к. помогают при расчете остатков и других клевых штук.. больше я вам ничего не скажу,… как-то так»
(23) e.kogan, хитро придумано )) я, честно говоря, тупо общий модуль перетащил в свое время в самописную конфу и поудалял оттуда все лишнее.
Одно отличие тут может стать заметным — если общий модуль может быть серверным, то форма — нет.
Был приятно удивлен появлением ссылки на статью на главной странице в рубрике «Выбор экспертов».
Хоть статья уже и не новая, я все же надеюсь, что она окажется познавательной в том числе и для тех, кто перейдет по ссылке из чистого любопытства. Для меня в свое время и сами-то роли в СКД были довольно загадочным явлением, а уж о таком странном поведении платформы я и вовсе не подозревал.
Самое удивительное и смешное во всей этой истории — это постоянные разговоры восьмёрочников о том, что восьмёрка якобы на порядок круче и эффективнее чем 7.7.
Да это же стыд и срам.
Это называется прогрессивная платформа!
Для написания обычного отчёта на СКД приходится залезать в дебри такого извращённого бреда, в который любой обкуренный шаман с бубном побрезгует соваться.
Вы хоть сами понимаете, что вместо нормальной и стабильной программерской работы, занимаетесь совершенно ненормальным «научным тыком» ???
Для странного, алогичного поведения платформы вы ищете странные, алогичные методы багофиксинга.
И я бы ещё понял, если бы выгода от использования СКД была настолько существенна, что перекрывала бы эти затраты времени и рассудка.
Но ведь этого не происходит.
Насколько я понимаю, основным плюсом СКД декларировалась очень высокая скорость разработки отчётов и, как следствие, экономия времени программиста?
Ну и?
Много времени сэкономили, бегая с бубном вокруг сабжа?
(29) Пацталоцци, я не вполне понимаю — какие есть альтернативы? Забить на СКД и перевести всех клиентов обратно на 7.7?
Мы работаем с теми механизмами, какие есть, а претензии имеет смысл адресовать не сюда, а к 1С.
(27) Пацталоцци, в любом случае, в статье идет речь об ошибке, которая проявляется в довольно специфичных условиях. Обычно для разработки простого отчета на СКД никаких сакральных знаний не требуется, достаточно просто написать запрос.
(31) Ничего себе специфические условия — поле остатка в запросе. В Бухгалтерии таких вобще-то процентов 90.
Столкнулся с ситуацией, когда прописывания ролей полям оказалось недостаточным. Пришлось сделать обязательным 2 поля: период и регистратор. (на то как отчет выдается пользователю не влияет, только на процедуру расчета.)
Дополнение
Пришлось и все измерения обязательными сделать (т.к. иначе отсутствие/наличие одного из измерений в запросе влияло на остаток 🙁 ) зато теперь работает как часы.
(32) nafa, обычно поля остатка правильно распознаются конструктором СКД и роли им прописываются без участия программиста. Конечно, можно заполнять схему компоновки программно, а не интерактивно. В этом случае роли приходится прописывать вручную, но это все же довольно специфичная ситуация.
(33)
Поля остатка то распознаются, но почему без этих галок то в самом примитивном отчете по регистру (простой запрос типа выбрать измерение1, измерение2, начальный остаток, приход, расход, конечный остаток, период, регистратор из регистр.ххх.ОстаткиИОбороты(,, Регистратор,)) итог по полям остатка при наличии в выбранных пользователем группировках периода/регистратора и их отсутствии оказывается совершенно разный, а с галками одинаковый.
(Отчет создан без единой ручной правки, только эти галки)
(34) nafa, да, насчет этих галок вообще вопрос интересный.
А если пользователь, к примеру, будет группировать отчет по периоду, но с заранее неизвестной периодичностью (неделя или месяц)? Делать оба поля ПериодНеделя и ПериодМесяц обязательными? Как на это отреагирует СКД? Надо будет проэкспериментировать и дополнить статью результатами эксперимента…
(35)
Есть есть обязательные группировки Регистратор и Период, то пруппировки ПериодМесяц и ПериодНеделя обязательными делать не надо, и так работает. Кроме того в статье по ссылке выше написано что нельзя одновременно использовать неделю и более крупные периоды — можно, но просто надо понимать что в этом случае неделя которая находится на пересечении месяцев разделится на два кусочка.
Полезная статья.
Спасибо автор.
Поставил обязательными поля Период и Регистратор. Остатки теперь выводит правильно, но по периодам перестал отчёт работать. В чём может быть причина?
Потратил полдня на это, нигде не видел, что периодичность виртуальной таблицы должна быть «Авто». У меня было «Регистратор» — ничего не получалось, пока не поменял на «Авто»…
(32) nafa, спасибо тебе, мил человек! перерыл пол-интернета, но только в твоём комментарии нашёл истину: «Пришлось сделать обязательным 2 поля: период и регистратор.»
(32) nafa, спасибо! Присоединяюсь «обязательно»!
Спасибо. Статья помогла разобраться в проблеме!
Автор, исправьте ссылку на Мисту в конце публикации, а то открывается не то!
(43)Ссылка на статью
https://its.1c.ru/db/metod8dev/content/3093/hdoc
(3)(6)Столкнулся с ситуацией когда остатки считались неверно до тех пор, пока не поставил галочки «Обязательное» и у «Регистратор» и у «ПериодСекунда».
Исправил все как в этой статье. Остатки считает правильно, но выводит как то странно.
2-мя строчками. В 1 строчке в полях начального и конечного остатка суммы начального остатка, а во второй строчке суммы конечного остатка. Подскажите, пожалуйста, кто сталкивался с таким? Заранее благодарен.