Универсальная свертка итогов оперативного учета и двигатель регистров




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

65 Comments

  1. skonto

    Поясните комментарий при попытке скачивания «Только спецагенты автоматизации могут скачивать этот файл»

    Reply ↓
  2. support

    🙂 это наше сообщение, сейчас исправим.

    Это значит, что автор разработки поставил ограничение на скачивание файла, и его могут скачать только те, кто разместил на портале свою разработку, и она получила рейтинг не меньше 3.

    Reply ↓
  3. viacht

    Этот файл могут скачивать только те, кто добавил свою программу или статью, и набрал рейтинг выше 3 баллов. Фигня такая вот выскакивает. Кто скачал — поделитесь.

    Reply ↓
  4. sashulyT

    Мне кажется надо более подробно описание написать 🙂

    Reply ↓
  5. KOCMOC™

    Молодца, улыбнуло 🙂

    Reply ↓
  6. poppy

    Снижено требования к скачиванию. Теперь могут скачивать зарегистрированные пользователи.

    Reply ↓
  7. Поражен новизной идеи

    Reply ↓
  8. poppy

    Ничего нового в идее нет. Это скорее классика…

    Reply ↓
  9. CheBurator

    Бяка.

    Я так понимаю, что документы до даты свертки удаляются…?

    Очистка периодики до даты свертки…?

    Есть тонкости в задании например кред.документа для регстра Взаиморасчеты…

    Reply ↓
  10. CheBurator

    Что плохо:

    — навскидку не удалось открыть документ в режиме редактирования.

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

    — а почему ограничились 10 измерениями — вдруг у меня — 11?

    итого — бяка…

    Есть более красивое решение по универсальному двигателю регистров

    картинки здесь:

    http://infostart.ru/file.php?0,file=377

    http://infostart.ru/file.php?0,file=378

    http://infostart.ru/file.php?0,file=379

    ..

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

    Reply ↓
  11. CheBurator

    в итоге: пришлось «откатиться» к штатной свертке…

    если ячего не так сдела/понял — просьба меня поюзать…

    Reply ↓
  12. CheBurator

    Нет, все-таки возвернулся…

    +1

    За простоту и эффективность!

    Reply ↓
  13. CheBurator

    Единственное — немного бы ускорил процесс за счет определения первого созданного документа свертки — по определению алгоритма — он лежит в конце дня после сворачиваемых документов, и выборку документов для удаления делал бы ДО ЭТОГО ДОКУМНТА, избежав на каждый удаляемы документ «СЗ.НайтиЗначение»

    Reply ↓
  14. CheBurator

    Процесс немного ускорил, как описал ниже.

    + еще одна бяка: _отображаются_ суммы в документе для ПартииНаличие и Взаиморасчетов покупателей/поставщиков — почему-то без десятичных разрядов (именно отображаются, так как в регистр пишется все что надо)

    Reply ↓
  15. CheBurator

    При этом Банк и Касса — ресурсы показываются как надо — с десятичными разрядами…

    Что скажет автор?

    Reply ↓
  16. CheBurator

    Где-то автор накосячила с процедурой ПриВыбореРегистра()

    Если открывается существующий документ — где происходит назначение типов неопределенным реквизитам ТЧ?

    и попутный вопрос: назначение типа происходит для всего столбца ТЧ дока или только для текущей строки…?

    А?

    Reply ↓
  17. CheBurator

    Да.. обработка требует доработки не надфилем — а драчовым напильником…

    Reply ↓
  18. poppy

    (16) Где-то автор накосячила с процедурой ПриВыбореРегистра()

    В чем конкретно накосячено?

    Назначение происходит при вводе новой строки…

    Reply ↓
  19. poppy

    (14) и (15)

    Ничего не скажу…

    Описанная ситуация не воспроизводится.

    Reply ↓
  20. poppy

    (10)

    > навскидку не удалось открыть документ в режиме редактирования.

    В каком случае?

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

    записано как пожелание (© 1С) 😉

    > а почему ограничились 10 измерениями — вдруг у меня — 11?

    В этом есть некий элемент неуниверсальности. Более универсальное решение http://infostart.ru/file.php?0,file=377

    Но, в рамках решаемой задачи:

    — для моего решения проще заполнять документ остатками. Всего три строчки кода:

    Код
          Табл = СоздатьОбъект("ТаблицаЗначений");
          Запрос.Выгрузить(Табл, 1, 0);
          Док.ЗагрузитьТабличнуюЧасть(Табл);
    

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

    — любой программист может легко увеличить рассматриваемое ограничение;

    — более десяти измерений = это скорее нонсенс, чем правило.

    Reply ↓
  21. poppy

    (9)

    > Я так понимаю, что документы до даты свертки удаляются…?

    Помечаются на удаление

    > Очистка периодики до даты свертки…?

    Нет. Надо бы добавить.

    Но в типовых решениях на ОУ редко используются периодические реквизиты, устанавливаемые документами. В этом случае, периодику можно «почистить» другими средствами.

    > Есть тонкости в задании например кред.документа для регстра Взаиморасчеты…

    Напиши подробнее.

    Reply ↓
  22. CheBurator

    (18) Открываем документ ссуществующими строками.

    Вопрос: где происходит назначение формата реквизитов-колонок?

    Reply ↓
  23. CheBurator

    > > Есть тонкости в задании например кред.документа для регстра Взаиморасчеты…

    это из области «доводки», но тем не менее — сворачиваю ОУ, мне не нужны расчеты с клиентами в разрезе кредитных доков (забъем на них!) — просто запишем долг. В этом случае — при проведении дока в измерение кредитного дока будет затолкнуто «пустое» значение — в принципе можно и так, но это считается некомильфово — в типовой Тис в этом случае — в качестве кридитного дока пишется сам документ ввода остатков.

    ..

    ща «куклу» по свертке доделаю — выложу для Типовой Тис с уточнениями, периодикой и прочей шнягой такой как полное удаление истории доков до свертки.

    Reply ↓
  24. CheBurator

    Еще бяка: не проводится контроль ссылочной целостности.

    как пример: возврат покупателю введен на основании реализации с интервалом в полгода. Где-то на этом интервале делаем свертку. В результате — в возврате будет бяка на суммах себестоимости «возвращаемой партии» — так как партия помечена на удаление…

    Reply ↓
  25. poppy

    (22)

    Вот код:

    Код
    Процедура ПриРедактированииНовойСтроки()
       Для ии = 1 по Метаданные.Регистр(СокрЛП(НаимРегистра)).Измерение() Цикл
          Тип = Метаданные.Регистр(СокрЛП(НаимРегистра)).Измерение(ии).Тип;
          Вид = Метаданные.Регистр(СокрЛП(НаимРегистра)).Измерение(ии).Вид;
          Тип = Тип + ?(ПустоеЗначение(Вид) = 1, "", "." + Вид);
          Форма.ПолучитьАтрибут("Измерение" + ии).НазначитьТип(Тип, Метаданные.Регистр(СокрЛП(НаимРегистра)).Измерение(ии).Длина, Метаданные.Регистр(СокрЛП(НаимРегистра)).Измерение(ии).Точность);
          Форма.ПолучитьАтрибут("Измерение" + ии).Доступность(1);
       КонецЦикла;
       Для ии = 1 по Метаданные.Регистр(СокрЛП(НаимРегистра)).Ресурс() Цикл
          Форма.ПолучитьАтрибут("Ресурс" + ии).НазначитьТип("Число", Метаданные.Регистр(СокрЛП(НаимРегистра)).Ресурс(ии).Длина, Метаданные.Регистр(СокрЛП(НаимРегистра)).Ресурс(ии).Точность);
          Форма.ПолучитьАтрибут("Ресурс" + ии).Доступность(1);
       КонецЦикла;
    КонецПроцедуры
    

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

    Reply ↓
  26. poppy

    (23) >это из области "доводки", но тем не менее — сворачиваю ОУ, мне не нужны расчеты с клиентами в разрезе кредитных доков (забъем на них!)

    В результате действий моей обработки регистры остаются в неизменном виде. Поэтому она и называется "Универсальная…".

    С другой стороны в обработке есть код:

    Код
    // Здесь можно указать измерения регистров, по которым детализация в новом периоде не нужна
    Если "Регистр.ПартииТоваров.ПрихДокумент" = "Регистр."+Метаданные.Регистр(и2).Идентификатор+"."+Метаданные.Регистр(и2).Измерение(ии).Идентификатор Тогда
       Продолжить;
    КонецЕсли;
    

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

    Таких конструкций ЕСЛИ может быть несколько. В каждой из них нужно указать регистр+измерение, значения которых не нужны для дальнейшего учета. Вместо них будут пустые значения.

    В качестве развития функционала можно рассматривать следующее.

    Пользователь может редактировать список регистр+измерение интерактивно. Плюс назначать значения по-умолчанию.

    Reply ↓
  27. poppy

    (23) >ща «куклу» по свертке доделаю — выложу для Типовой Тис с уточнениями, периодикой и прочей шнягой такой как полное удаление истории доков до свертки.

    ИМХО тоже самое делает типовая свертка ТиС. Чем она тебя не устраивает?

    Reply ↓
  28. poppy

    (24) > В результате — в возврате будет бяка на суммах себестоимости «возвращаемой партии» — так как партия помечена на удаление…

    Во-первых, рассматриваемая обработка не помечает справочники на удаление.

    Во-вторых, если элемент справочника помечается на удаление, это не значит, что должны измениться остатки в регистрах.

    В-третих, документ «Возврат от покупателя», для расчета себестоимости, использует значения регистра(ов). Как было сказано в (26) регистры не меняются (имеется в виду от даты сверткти+1 и далее) значит действия документа также не изменятся.

    ИМХО ты что-то путаешь.

    Reply ↓
  29. CheBurator

    Сам ты путаешь. Если док-основание возврата от покупателя помечен на удаление — отсутвуют итоги по его партии. себестоимость возвратов тянуть неоткуда…

    Reply ↓
  30. poppy

    (29)

    Док-основание возврата от покупателя — это, как правило, Реализация. Что такое "отсутвуют итоги по его партии" применительно к документу Реализация — не пойму.

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

    В глобальном модуле есть процедура глВыяснитьПартииВозврата(), где определяется себестоимость возвращаемых партий. Там есть условие:

    Код
       Если (ТекДок.ДокОснование.Выбран()=1) и (Свернут=0) Тогда
    

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

    Что-бы "избавиться" от зависимости возврата от движений основания достаточно установить реквизит ФлагСвертки документа-основания, если он имеется, в единицу . Или очистить реквизит ДокОснование самого документа. При этом, партии и их себестоимость нужно перенести в табличную часть документа-возврата. Естественно, нужно учитывать текущее состояние ГП.

    Считаю, что такой алгоритм "пихать" в универсальную обработку = неразумно. Как вариант, можно написать отдельную обработку, которая "подготавливала" бы базу к свертке. Естественно, эта обработка должна быть "заточена" под конкретную базу. Эту обработку заставлять запускать пользователя или подключать ее как плагин.

    Reply ↓
  31. CheBurator

    > Как вариант, можно написать отдельную обработку, которая «подготавливала» бы базу к свертке. Естественно, эта обработка должна быть «заточена» под конкретную базу.

    ..угум, так и подточил в некоторых местах…

    Reply ↓
  32. mihenius

    Попытка это сделать (31)

    http://infostart.ru/projects/1259/

    Reply ↓
  33. CheBurator

    На основе эксплуатации выявлен еще ряд неприятных багов, в первую очередь связанных с работой с измерением, которе задается числом: например: ЦенаПрод в ОстаткахТМЦ и ПартияхНаличие — отображаются на форме докамкриво после открытия дока и манипуляции с ним — дробные части ек…

    Reply ↓
  34. CheBurator

    например, в доке записано цена продажи = 23.80

    на форме !!отражается!! целочисленное значение — при проведении — записывается верный результат…

    где коссяк в отображении — навскидку не нашел…

    Reply ↓
  35. poppy

    (33, 34)

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

    Такое поведение считаю фичей платформы.

    Отображение только целочисленной части числа не замечено. Возможно, это связано с особенностями конкретного релиза платформы (я использую 25-й) или использованием внешних компонент (я не использую).

    Reply ↓
  36. poppy

    Были нарекания при свертке больших баз.

    В версии от 1.02.08 количество строк в создаваемых документах ограничено тысячей.

    Reply ↓
  37. CheBurator

    (35) скинуть базу (урежу до минимума с траблой)?

    Reply ↓
  38. poppy

    (37) Давай

    Reply ↓
  39. Вадимко

    А почему используешь запрос а не выгрузить итоги? 🙂

    Reply ↓
  40. poppy

    (39)

    От этого что-то изменится?

    Reply ↓
  41. Вадимко

    (40) Скорость 🙂

    Если там будет 5-6 группировок… по пухлому регистру…

    Нехорошо конечно пиарить, но посмотри мою обработочку для SQL

    Reply ↓
  42. Вадимко

    (40) Скорость

    Reply ↓
  43. Вадимко

    Сорри… глюкает что-то

    Reply ↓
  44. poppy

    (41)

    2Вадимко

    В моей обработке упор сделан на универсальность и простоту кода.

    Неоспоримым преимуществом является неиспользование ВК.

    Reply ↓
  45. Ёпрст

    Жалко что вариант не совсем рабочий 🙁

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

    Reply ↓
  46. Bobak

    (45)Какая ошибка?

    Reply ↓
  47. Ёпрст

    (46) Древняя 🙂

    Для измерений/Реквизитов неопределенного типа будет дырка от бублика…

    тип надобно изначально назначить…

    Reply ↓
  48. poppy

    (47) Пожелание принято. Списибо.

    Reply ↓
  49. Ёпрст

    (48) та не за что, такая же ошибка почти во всех обработках, где копируются реквизиты документов в обход метаданных… все как-то забывают про неопределенный тип данных…потом долго удивляются отсутствием данных:)

    Reply ↓
  50. IsiKosta

    Хорошее и простое решение.

    Однако можно добавить:

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

    2) проверить наличие документа для свертки;

    3) при запуске задать дату свертки (например начало текущего года).

    Reply ↓
  51. poppy

    (50) Спасибо за пожелания.

    Reply ↓
  52. markinleha

    Все понравилось, только поставил удаление документов в транзакцию и добавил пару галок на форму, «свернуть регистры» и «удалить документы», чтобы запускать нужное мне дйствие, ибо метит долго и делает это сразу, быстрее свернуть регистры прибить таблицы движений и потом пометить на удаление.

    Reply ↓
  53. rm123

    Производство+Услуги+Бухгалтерия, редакция 2.8 свернет

    Reply ↓
  54. poppy

    (53) Свернет. Но остатки будут только в регистрах.

    Reply ↓
  55. rm123

    по счетам надо будет ручками остатки вводить?

    как бы его скачать получить?

    Reply ↓
  56. Mixa45

    Я свернул 1С Предприниматель 7.7. Документы помеченные на удаление не удаляются, т.к. ссылаются на созданные регистры. Кто знает что делать?

    Reply ↓
  57. Lucifer_i

    Можно чуток ускорить, если в цикле использовать не «Сообщить()», а «Состояние()». Т.к. «Сообщить()» работает до ужаса медленно. 🙂

    Reply ↓
  58. Andre_ultra

    Спасибо — это в данном случае не то слово. Вам жмут руки огромное число пользователей. Добавил только перенос старых документов по ссылкам из удаляемого периода. Это нужно для того, чтобы база осталась полностью перепроводимой.

    Reply ↓
  59. Energen

    Помогло при свертке базы данных «Торговля и Склад» 9.х, у которой был критический размер файла регистра расчетов с покупателями. Все вроде бы неплохо, но для моей БД, размер которой был около 4 гигабайт, таблицы получились до 40 000 записей, соответственно документ «Двигатель регистров» работает очень не быстро, даже при наличии внешней компоненты. Свертку делал на своем ноутбуке с RAID0 на SSD дисках, т.к. на сервере с двумя Xeon и RAID10 на шести HDD получалось гораздо дольше…

    Автору огромное спасибо!!!

    Reply ↓
  60. nkvg_a

    Спасибо! и ваша обработка сгодилась для свертки комплексной с базой в 3 г

    Reply ↓
  61. corsar4ik

    Поплыли остатки по счетам в комплексной 512.

    Reply ↓
  62. mimos

    Свернул базу Тис размером в 8г -0 теперь размером в 2 гига. Всё нормально, только жалко партии на документ движения не перенеслись. поэтому старые документы удалить не получается. Свернулось всё быстренько и аккуратненько.

    Reply ↓
  63. Sergafan10

    Подскажите пожалуйста, можно ли исправить Вашим документом несписанную (задним числом!) себестоимость, которая возникает при ругани «Не распределилось по партиям…» (пустые партии продают) ???

    Reply ↓
  64. ЛохНесс

    [63]

    Умеючи — можно…

    Reply ↓
  65. niko11s

    Спасибо.

    Reply ↓

Leave a Comment

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