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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2024-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 не будет опубликован. Обязательные поля помечены *