Сброс неверной нумерации объектов




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

26 Comments

  1. seermak

    + за подробность и старание)))

    Reply ↓
  2. Angel_19

    Блин, это только для управляемых форм?

    Reply ↓
  3. magobato

    (1) seermak, спасибо))

    Reply ↓
  4. magobato

    (2) Angel_19, да, обработка работает только в управляемом интерфейсе. в крайнем случае, если позволяет платформа, можете запустить конфигурацию в режиме тонкого клиента и после этого воспользоваться обработкой.

    Reply ↓
  5. Светлый ум

    Для документов пришлось сделать так:

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

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«Справочники»);
    Элементы.ВидМетаданных.СписокВыбора.Добавить(«Документы»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«БизнесПроцессы»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«Задачи»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«ПланыВидовРасчета»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«ПланыВидовХарактеристик»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«ПланыОбмена»);
    //Элементы.ВидМетаданных.СписокВыбора.Добавить(«ПланыСчетов»);
    
    ВидМетаданных = Элементы.ВидМетаданных.СписокВыбора[0].Значение;

    Показать

    Reply ↓
  6. jobkostya1c8

    А я проще сделал, обработка с двумя реквизитами — (ссылку на плохую счет-фактуру и «НовыйНомер») и тремя кнопками код ниже:

    //1. Шаг Прочитать некорректный и макс номер
    Процедура КнопкаВыполнитьНажатие(Кнопка)
    СФОбъект = СсылкаНаОбъект.ПолучитьОбъект();
    //СФОбъект.Номер = «»; // 12 цифр
    Сообщить(«До функции УстановитьНовыйНомер() СФ «+СФОбъект.Номер);
    СФОбъект.УстановитьНовыйНомер();
    Сообщить(«после применения функции Некорректный номер «+СФОбъект.Номер);
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ ПЕРВЫЕ 1
    | СчетФактураВыданный.Ссылка,
    | СчетФактураВыданный.Номер КАК Номер,
    | СчетФактураВыданный.Дата
    |ИЗ
    | Документ.СчетФактураВыданный КАК СчетФактураВыданный
    |
    |УПОРЯДОЧИТЬ ПО
    | Номер УБЫВ»;
    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();
    Сообщить(«Максимальный номер «+Выборка.Номер);
    // Вставить содержимое обработчика.
    КонецПроцедуры
    
    // Шаг 2 установить новый  номер
    Процедура ОсновныеДействияФормыДействие(Кнопка)
    СФОбъект = СсылкаНаОбъект.ПолучитьОбъект();
    //СФОбъект.Номер = «»; // 12 цифр
    СФОбъект.УстановитьНовыйНомер();
    Сообщить(«Новый номер «+СФОбъект.Номер);
    СФОбъект.Номер = СокрЛП(ЭтотОбъект.НовыйНомер);
    СФОбъект.Записать();
    Сообщить(«СФ стала»+СсылкаНаОбъект);
    КонецПроцедуры
    
    // Шаг 3 ОбновитьНумерациюОбъектов(«ИмяДок») гл контекст
    Процедура КоманднаяПанель1ОбновитьНумерациюОбъектов(Кнопка)
    парамОбъектМетаданных = СсылкаНаОбъект.Метаданные();
    ОбновитьНумерациюОбъектов(парамОбъектМетаданных);
    Сообщить(«Для объекта метаданных «+парамОбъектМетаданных+» обновлена нумерация. Все ранее выданные, но незаписанные в базу стали недействительными!»);
    КонецПроцедуры
    
    

    Показать

    Как Вам такой подход. Главное, что все заработало.

    Reply ↓
  7. sly2k

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

    Reply ↓
  8. zvv77

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

    Reply ↓
  9. BBDragon

    Странно, а у меня нумерация не исправляется. Кэш на сервере чистил, Агент сервера предварительно остановив. Как я ни делаю — следующий номер остается неправильным

    Reply ↓
  10. user856012

    (9)

    Как я ни делаю — следующий номер остается неправильным

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

    Reply ↓
  11. BBDragon

    Я поясню. В октябре сбили нумерацию счетов-фактур в УТ 11.3, вручную изменив номер и он теперь стал начинаться с 2 нулей, а не с 3 как было. Последний такой номер, присвоенный вручную был 8956, т.е. вместо 00ЦБ-0008956, сделали 00ЦБ-008956. Я изменил этот номер вручную на правильный формат 00ЦБ-0008956 и перезапустил обработку — не помогло(

    Единственное, если раньше он показывал, что следующий номер будет 00ЦБ-008957, то теперь на единицу меньше — 00ЦБ-008956.

    Перенумерация с помощью обработки «Универсальный подбор и обработка объектов» также не дала результатов (префикс там тоже пробовал менять). Существующие СФ она перенумеровывает, а новой опять присваивается номер с двумя нулями, а не с тремя. Пробовал вручную парочку новых СФ сформировать и прописать правильный номер — опять не помогает. Как все-таки можно изменить этот параметр «Следующее значение»?

    Reply ↓
  12. user856012

    (11)

    Единственное, если раньше он показывал, что следующий номер будет 00ЦБ-008957, то теперь на единицу меньше — 00ЦБ-008956.

    Заставляет предположить, что где-то сидит счет-фактура с номером 00ЦБ-008955.

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

    Проверить это несложно: создать 00ЦБ-008956, можно еще для уверенности 00ЦБ-008957, потом их удалить и сбросить автонумерацию. Если после этого программа будет предлагать 00ЦБ-008958 — значит, обработка не сработала, нумерация не сбросилась.

    Ну, а если вернется к предложению 00ЦБ-008956 — наверняка существует 00ЦБ-008955, надо его искать и удалять.

    Reply ↓
  13. BBDragon

    Да, есть такая.. Их там вообще куча в 3-ем квартале еще..

    00ЦБ-005763 10.07.2017 0:00:00

    00ЦБ-006915 01.08.2017 23:59:59

    00ЦБ-007515 15.08.2017 23:59:59

    00ЦБ-007606 08.08.2017 23:59:59

    00ЦБ-008170 11.09.2017 23:59:59

    00ЦБ-008225 12.09.2017 23:59:59

    00ЦБ-008598 01.07.2017 14:50:19

    00ЦБ-008606 14.07.2017 17:42:48

    00ЦБ-008607 14.07.2017 17:42:50

    00ЦБ-008609 21.07.2017 23:59:59

    00ЦБ-008611 21.07.2017 23:59:59

    00ЦБ-008616 05.07.2017 18:15:46

    00ЦБ-008618 05.07.2017 18:15:48

    00ЦБ-008619 05.07.2017 18:15:50

    00ЦБ-008620 05.07.2017 18:15:52

    00ЦБ-008621 05.07.2017 18:15:54

    00ЦБ-008785 06.07.2017 9:04:44

    00ЦБ-008790 20.07.2017 23:59:59

    00ЦБ-008791 31.07.2017 23:59:59

    00ЦБ-008796 18.08.2017 23:59:59

    00ЦБ-008799 19.08.2017 23:59:59

    00ЦБ-008807 12.09.2017 23:59:59

    00ЦБ-008808 04.09.2017 23:59:59

    00ЦБ-008810 29.09.2017 23:59:59

    00ЦБ-008817 16.06.2017 17:06:20

    00ЦБ-008818 14.06.2017 19:50:18

    00ЦБ-008819 23.06.2017 16:46:35

    00ЦБ-008820 22.06.2017 23:59:59

    00ЦБ-008821 21.06.2017 0:00:00

    00ЦБ-008885 10.10.2017 23:59:59

    00ЦБ-008924 22.07.2017 22:12:17

    00ЦБ-008925 18.07.2017 23:59:59

    00ЦБ-008926 12.07.2017 20:00:28

    00ЦБ-008927 07.07.2017 17:38:37

    00ЦБ-008928 23.08.2017 23:59:59

    00ЦБ-008930 28.09.2017 23:59:59

    00ЦБ-008931 26.09.2017 23:59:59

    00ЦБ-008932 25.09.2017 23:59:59

    00ЦБ-008933 14.09.2017 23:59:59

    00ЦБ-008934 13.09.2017 23:59:59

    00ЦБ-008935 12.09.2017 23:59:59

    00ЦБ-008937 10.09.2017 14:33:46

    00ЦБ-008938 07.09.2017 23:59:59

    00ЦБ-008939 06.09.2017 23:59:59

    00ЦБ-008941 06.09.2017 23:59:59

    00ЦБ-008942 20.07.2017 23:59:59

    00ЦБ-008947 11.10.2017 0:00:00

    00ЦБ-008948 04.10.2017 23:59:59

    00ЦБ-008949 02.10.2017 23:59:59

    00ЦБ-008951 14.09.2017 23:59:59

    00ЦБ-008952 13.09.2017 23:59:59

    00ЦБ-008953 15.07.2017 12:00:52

    00ЦБ-008954 19.08.2017 23:59:59

    00ЦБ-008955 12.09.2017 23:59:59

    При этом в 4 квартале уже есть счета-фактуры с такими же номерами, только с 3 нулями в начале (8924-8955). В общем решил не трогать 3 квартал, оставить как есть, с 2 нулями, надо теперь лишь нумерацию в 4 квартале поправить, чтобы не было дублирующих номеров. Ибо в СФ на печати лидирующие нули уходят и получается что счет-фактуры к 2 разным реализациям имеют одинаковый номер.

    Reply ↓
  14. progr-2008

    (1)А есть такая обработка для обычных форм?

    Reply ↓
  15. quietbuh

    Объясните пожалуйста на пальцах в какой последовательности нужно выполнять чтобы исправить нумерацию. Не получается, все равно создает след. кривой номер.

    Reply ↓
  16. magobato

    (15) последовательность в конце статьи указана. По сути:

    выбираете тип объекта.

    система подбирает объекты

    флагом Макс. указываете на тот номер, который хотите чтобы считался максимальным

    нажимаете на «обновить».

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

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

    Reply ↓
  17. churlena

    Спасибо за обработку! Мне очень помогла в критический момент)

    Reply ↓
  18. k992007

    спасибо за обработку

    Reply ↓
  19. aljir

    Спасибо за обработку!

    Reply ↓
  20. GlukAl

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

    Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    Если ЭтоНовый() Тогда УстановитьНовыйКод(«0»); КонецЕсли;
    КонецПроцедуры

    и не важно, что пользователи вводили в поле код ранее

    нумерация для новых элементов будет с 0000

    Reply ↓
  21. sergathome

    Автор, огромное спасибо. Сподвиг меня на победу над этой дурой — нумерацией. Хакерский ход возможен, однако. Задача: 1C-Бухгалтерия 3.0, бухша завела реализацию задним числом и настаивает на сохранении номера, хотя её номер сбивает нахрен всю нумерацию (было, условно, 00БП-0000, бухша сделала 00БП-00/1, требуется вернуть 00БП-0000). Дополнительная вводная — нумерация реализации в бухгалтерии ведётся за год (!) это важно. Как действует 1С при захвате номера — она подаёт запрос к таблице документа и вычисляет максимум самым простецким способом, при выполнении ОбновитьНумерациюОбъектов этот запрос ловится профайлером (если кому интересно) — так можно узнать имя таблицы документа. Далее, как известно из https://its.1c.ru/db/metod8dev#content:1798:hdoc, номер относится к периоду посредством

    _NumberPrefix — начало периода уникальности номера. Поле определено, если в конфигурации для документа задана поддержка уникальности номера в пределах периода; поле представляет из себя дату в обычном формате SQL, где к году прибавлено 2000, например что- типа 4019-01-01. Изменив эту дату, например на 4010-01-01, мы выкинем номер из периода 2019 года. И восстановим нумерацию, не прибегая к смене «аварийного» номера…

    Скрипт для MS SQL (для Бухгалтерии):

    — Переносит максимальный номер в другой год, освобождая тем самым предыдущую серию номеров
    — Например, если был введен номер 00БП-00635/1, то к номеру 00БП-003335 вернуться просто так не удастся,
    — этот скрипт выкидывает самый старший номер в другой период.
    — Формат хранения дат — год+2000, слава великому 1С!
    UPDATE dbo._Document372
    SET _NumberPrefix = ‘4010-01-01’ — этот период устанавливается
    WHERE _Number IN (SELECT
    MAX(T1._Number)
    FROM dbo._Document372 T1
    WHERE _NumberPrefix > ‘4018-01-01’) — период отбора

    Показать

    Reply ↓
  22. iGracefull2

    (21) Аналогичная задача, но на файловой базе:( Нужно сохранить доки с неправильной нумерацией, при этом, задать последующуюу верную нумерацию. То есть Шли номера 0000000841, 0000000842, 0000000843, затем вручную вбили корявый номер 00000843.1, далее нумерация подцепила и пошла автоматом в 00000843.2, однако бухам надо, что бы был 0000000844. Есть варианты как это поправить, не сломав нумерацию старую?

    Reply ↓
  23. magobato

    (22) Навряд ли получится. Чтобы «играться» периодами как в (21) нужен прямой доступ к таблицам, а в файловом варианте это проблематично.

    По идее, нумерация не собьется, если неправильный номер номинально меньше правильного. Например в базе правильный номер Б1, вводится неправильный — А1, тогда система всё равно продолжит нумерацию с префиксом «Б» и следующий номер будет Б2.

    Поэтому, как вариант решения данной проблемы — использование префиксов.

    Reply ↓
  24. sergathome

    (22) загрузить базу на сервер, исправить и выгрузить назад. Никакие другие махинации в вашем случае не помогут ибо 00000843.1 будет всегда гарантированно больше любого «нормального» номера.

    Reply ↓
  25. sergathome

    (23) Чем хренова такая модель нумерации, так это тем, что она противоречит «интуитивно понятной». Когда идёт нумерация 001, 002 и тп, то кажется логичным, при требовании «вклиниться» в такую нумерацию использовать дробь вида 001/1, к примеру. Однако использование нецифрового символа приводит к тому, что платформа начинает считать кусок номера 001/ префиксом со всеми вытекающими, и, мало того, поскольку символ находится в кодировочной таблице дальше цифр, такая серия кодов оказывается старше любой «нормальной» 🙁 1C традиционно самоустранилась типа это «особенность платформы» и идите в ж. Однако на практике не всё так просто, да.

    Reply ↓
  26. iGracefull2

    В общем-то так и случилось. Что бы я не делал, 843.1 был всегда последним номером. Пришлось кустарить периодический регистр нумерации объектов и присваивать номера оттуда. Так как сбили нумерацию порядка 3 разных типов документов и намерены дальше сбивать. Костыль, но что поделать

    Reply ↓

Leave a Comment

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