Байки разработчика №1: детективные

Вам не кажется, что работа разработчика 1С иногда похожа на увлекательный детективный сериал с непредсказуемым финалом? Думаю, все испытывали этот сладостный момент, когда после долгих блужданий в дебрях кода истина наконец найдена! Вот и со мной так было не раз. Предлагаю вашему вниманию несколько историй на эту тему.

Ручной обмен

Несколько лет назад, кажется в 2014 году, пришел как-то к нам на поддержку новый клиент.

У клиента много баз, много интеграций между ними. База, где ведется основной учет, за несколько лет переписана до неузнаваемости. Причем в разные моменты ее дорабатывали разработчики очень разной квалификации. Никакой документации нет, технических заданий нет, спросить в случае чего не у кого. Плюс ко всему, совместно с переходом к нам на поддержку происходил также и переезд с собственных серверов в забугорский дата-центр (в компании была реструктуризация), что также добавляло изрядное количество проблем. Все это добро свалилось к нам одномоментно, практически без каких-либо нормальных процессов приемки-передачи. В общем, никогда такого не было, и вот опять!

Клиент большой, важный и требовательный (а есть другие?). Начинаем в ускоренном порядке въезжать в его бизнес-процессы, знакомиться с IT-службой, настраивать сервера, обрабатывать заявки. Вдруг, в какой-то момент встает обмен между двумя самыми главными, самыми важными информационными базами. Обмен полностью самописный. Никаких вам универсальных механизмов, правил обмена, EnterpriceData или чего-то подобного. Из одной базы COM-ом цепляемся в другую базу, собираем данные и погнали. Только код, только Hardcore! 

Итак, обмен не работает. Ошибка абсолютно невразумительная и непонятная: «в данной транзакции уже происходили ошибки». ОК, уже происходили, понятно, вернее — не понятно, дальше что? 

Ладно, открываю конфигуратор в боевой базе (нет времени собирать какие-то тестовые стенды), ставлю точки останова, запускаю обмен. Выявил процедуру, где возникает ошибка. Уже хорошо. В этой процедуре также ставлю точку останова и иду построчно по F10. Пытаюсь уже здесь выловить злосчастную строчку, где все падает, и… обмен проходит без ошибок. Что за чертовщина? Но времени разбираться нет. Отписываемся клиенту, что обмен прогрузили, и едем дальше разруливать заявки.  

Но на следующий день (обмен ходил раз в сутки ночью) все опять повторяется. Регламентное задание не отработало. Та же ошибка. Снова конфигуратор, снова точки останова, F10, и снова обмен проходит без ошибок. 

Ближе к вечеру разворачиваю тестовые базы на нужную дату. Запускаю обмен – ошибка! Ставлю в конфигураторе режим «Остановка по ошибке». Ошибка есть, остановки нет! Иду отладчиком построчно – нет ошибок! Начинаю верить в магию и параллельные миры. Еду домой, много думаю.

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

Причина же оказалась в следующем: в процессе обмена шла запись некоторых служебных данных в некоторый служебный регистр, причем регистр был периодический с периодом в 1 секунду. Когда обмен запускался регламентным заданием, происходила запись в этот регистр одинаковых данных, соответственно обмен падал с ошибкой «запись не уникальна». Когда шли отладкой, между итерациями проходило больше одной секунды и все служебные данные записывались в регистр без ошибок. Остановка по ошибке не срабатывала, т.к. как весь обмен был написан «в попытке», а до этого момента в вышестоящей процедуре также была исключительная ситуация, которая на результат обмена не влияла, но не давала отловить ошибку записи в регистр (привет разработчику, который это написал).

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

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

 

Грузим грузим грузим остатки

Внедряли мы как-то 1С:ERP в одной крупной торговой сети. 

Еще в самом начале проекта появилась задача по загрузке остатков (куда ж без нее?) из действующей системы заказчика (не 1С). В качестве формата передачи данных выбрали Excel, т. к. в этом случае не требовалась доработка исходной системы.

Итоговая задача сводилось к следующему: необходимо было прочитать файл с остатками, получившиеся данные распознать, затем свернуть строки по набору полей «Организация, Склад, Подразделение, Номенклатура, Характеристика и т. д.» с суммированием количества и стоимости. Далее, для каждого набора «Организация, Подразделение, Склад» создавался отдельный документ «Ввод начальных остатков» с заполнением табличной части. Причем для простоты тестирования и отладки, а также чтобы не плодить лишние документы при каждой загрузке одного и того же файла, существующие документы, отвечающие параметрам поиска, перезаписывались. На форме обработки была соответствующая «галочка». В общем, все как обычно.

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

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

Сверяем итог в 1С с первоисточником – не сходится. Клиент выгружает файлы Excel еще раз, уверяет, что файлы созданы правильно. Консультант грузит файлы, сверяет каждый файл, все загружается верно. Общий результат все равно не сходится. Файлы огромные (общий объем под 200000 строк), грузятся долго. Поиск ошибки затягивается. Старт под угрозой, задача получает наивысший приоритет. Каждое звено цепи работает без ошибок, но остатки в двух системах никак не хотят сойтись. 

Как часто бывает, причина лежала на поверхности, но ее почему-то сразу никто не увидел. Дело в том, что клиент предоставил несколько файлов с остатками. И в разных файлах существовали строки с одинаковыми наборами «Организация, Подразделение, Склад» (и даже с одинаковой номенклатурой). Соответственно, следуя алгоритму, обработка загрузки пересоздавала некоторые документы, которые были созданы ранее при загрузке данных из других файлов. 

Загрузили файлы с небольшим смещением по времени (поиск происходил также и по дате документа) и остатки сошлись. 

 

Широка страна моя родная

«Зарплата и управление персоналом» версии 2.5. РИБ на 11 баз. Каждый филиал работает в своей базе, итоговые данные сливаются в центральный офис. 

Только что внедрен новый функционал – очень хитрый и сложный расчет оплаты сверхурочных часов. 

Приходит заявка – данные расчета переработок по одному сотруднику рассчитались неправильно.

Конфигуратор, отладка, получаю итоговый запрос, консоль запросов, вставлю в нужные места фильтры по сотруднику, выполняю, получаю результат. Расписываю, как и почему получены суммы, отдаю задачу. По всему получается, что все рассчитано верно. 

Консультант связывается с клиентом. Вместе решают, что да, все верно. Но вскоре задача возвращается: в филиале при расчете суммы другие. Так. Уже интересней.

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

Подключаюсь к базе филиала, делаю расчет, действительно, по одному сотруднику данные не сходятся с центром. Консоль запросов, фильтр по сотруднику – результат другой. Хм… Очевидно, дело в отличающихся исходных данных. Но где именно?

Как я говорил, алгоритм расчета нетривиальный, запрос под две тысячи строк, куча таблиц (во общем, как обычно и бывает в ЗУП). Начинаю плавно подниматься по запросу снизу-вверх, сравнивая значения временных таблиц. Где-то в середине запроса нахожу таблицу, с которой начинаются несоответствия. Иду дальше и натыкаюсь на регистр, ошибку в котором я совсем не ждал…

Дело в том, что этот филиал находится в Казани. А в Татарстане есть национальный праздник с плавающей датой – «Курбан-байрам», который в 2024 году выпал на 12 сентября. Соответственно, в производственном календаре это был выходной день, и работа в этот день считалась переработкой. А в центральной базе, где был общий Российский производственный календарь – это рабочий день. 

Описываю всю ситуацию. Отдаю задачу консультанту. Консультант звонит клиенту. Где-то в глубине души начинает зарождаться очень нехорошее предчувствие. И действительно… Задача приходит на доработку:

«Реализовать в системе возможность хранения нескольких производственных календарей»

Но это уже совсем другая история…

 

P. S. Смотрите также:

 

22 Comments

  1. Kaval88

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

    Reply
  2. bad_wag

    О да) Прочитал с удовольствием, надеюсь будет продолжение!

    Reply
  3. sailor-cat

    Добавлю свои 5 копеек, вспомнилось:

    У клиента файловая база однажды утром увеличилась с 2х до 8ми гигов и, естественно, отказалась запускаться.

    Разобраться помогла утилита Tool_1CD: оказалось, что все лишние 6 гигов пришлись на таблицы рассчитанных итогов.

    Оказалось, кто-то из сотрудников клиента провел документ 0012-м годом. А потом случился пересчет итогов.

    Reply
  4. user_gea

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

    Reply
  5. dsdred

    Про регистр натыкался лет 5 назад)) После московской франчайзи переделывал.

    У меня была еще забавная история, тоже лет 5 назад, переделывал после того же Московского франчайзи.

    Из 7.7 в 8 перетаскивали данные по себестоимости. Причем 1 документ формировал сумму, а второй расшифровка и тоже содержал суммы.

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

    Как то ко мне приходят аналитики и говорят а куда делась вот эта номенклатура??? И предъявляют мне ее список.

    Смотрю походу и ржу(понимаю что франчи просто сдали работу зная об этом косяке)…

    Есть сумма первого документа и есть счетчик сумм номенклатуры расшифровки.

    Берется первая номенклатура и ее стоимость ложится в счетчик.

    Счетчик сравнивается с сумой документа, если он меньше или равен номенклатура и сумма переносится.

    Затем берется следующая сумма добавляется к счетчику и опять сравнивается.

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

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

    Reply
  6. necropunk

    (3) Хехе, тоже такое было, остатки завели на 01.01.0001. И итоги за пару тыщ лет рассчитались.

    Reply
  7. kauksi

    про Press any key… рассказывали уже?

    Reply
  8. starik-2005

    Хых. Первое, что я обычно говорю клиентам и коллегам, обращающимся ко мне с проблемами: «чудес не бывает — чичас все найдем». И находим.

    Reply
  9. Разумов

    Ага, угадал автора по загол… а, блин.

    Reply
  10. Tavalik

    (9) По соседству посмотрите )

    Reply
  11. Ibrogim

    А у меня есть история, где решение оказалось в другом измерении )

    Серверная База 1С, обмен по регламенту с сайтом через прямой доступ к таблицам mySQL через ssh туннель. На сайте периодически появлялась беда с остатками (не правильные, нулевые, не те). Ковыряние в отладчике всегда показывало что всё правильно! Появилась вера в потусторонний мир.

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

    Хорошо, что сейчас при развёртывании копии базы платформа спрашивает, и если это копия отключает регламентные задания.

    Reply
  12. Tavalik

    (11)

    О да! Это очень частая ошибка. Мы еще много лет назад начали использовать механизм самоидентификации баз, который мало того, что отключает все регламентные задания, так еще и заголовок программы подменяет. Почитать об этом можно, например, здесь: https://infostart.ru/public/725524/

    Reply
  13. skif47

    Есть внешняя обработка с кучей форм. У некоторых клиентов, которые её используют, иногда происходила мистика: в большей части форм внезапно «пропадал» весь код. Т.е.форма есть, а все обработчики и экспортные методы из неё словно исчезли.

    Проявлялось непредсказуемо, на разных базах, у разных пользователей, на разных платформах 8.2 и 8.3. Разве что всегда на обычных формах и файловых базах.

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

    Причину искали долго. Сюжет для серии из «доктора хауса».

    Оказалось вот что. Во всех случаях были настроены «регламентные задания», запускающиеся под определённым пользователем (разумеется, именно под тем, кто обращался к нам с ошибкой). После завершения фондового задания в файловой базе платформа, видимо, обнуляет некий кэш в текущем сеансе. Формы, уже инициализированные к этому времени, остаются в памяти. А не инициализированные уже не получить до перезапуска внешней обработки.

    Разумеется, почти у всех клиентов интервал выполнения фоновых заданий был 60 секунд.

    Reply
  14. Tavalik

    (12)

    Блин, не та ссылка. Вот правильная: https://infostart.ru/public/647048/

    Reply
  15. Tavalik

    (7)

    Нет, что за история?

    Reply
  16. Tavalik

    (1)

    Эх, хотел оставить интригу в конце, но вопрос по видимому волнующий.

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

    P.S. Кстати, в ЗУП 3 возможность вести несколько календарей есть в типовом функционале.

    Reply
  17. kauksi

    (15)

    Reply
  18. katenok86

    (11)Было дело долго ловила почему при обмене с До в ерп не приходят актуальные статусы, оказалось их тестовые копии воруют))

    Reply
  19. katenok86

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

    Reply
  20. katenok86

    Еще из мистики настраивали согласование экземпляров бюджета созданных в ерп через документооборот и возврат назад статусов согласования. И вот в один момент экземпляры бюджета стали в ерп пропадать, был был а теперь битая ссылка. Долго боролась и не могла понять в чем дело, оказалось в До был создан служебный регистр в котором по экземпляру устанавливался некий реквизит с привязкой к ответственному. А потом было написано правило синхронизации Этот регистр в документ Экземпляр в ерп (по сути там просто менялся тоже реквизит). И если пользователь в До удалял запись из этого регистра то регистрировалось событие на удаление в обмене и в ерп удалялся документ. После переделки правил, чтобы при изменении в регистре регистрировался к выгрузке документ, ошибка ушла.

    Reply
  21. harmer

    Бывает и так, но это уже не детектив, а комедия.

    Reply
  22. koshak84

    Тоже была комедия один раз. Устроился на работу в новую компанию. Все хорошо, работали несколько месяцев, пока однажды не начали проводить работы с электричеством в здании. Отключили все сервера (по RDP). Когда пришло время их включать, прошлись по серверным и все включили с кнопки. Потом начали звонить, что складской базы нет. Попинговали — действительно нет. Может быть сервер не включили. Прошлись еще раз по серверным, все проверили, все включено, все сервера подписаны. А вот сервера с складской базой нет. Искали где физически стоит сервер весь день. У кого спрашивали — ни кто не в курсе. На следующий день вышли на бывшего админа, который сказал, что тот сервер был виртуальным и его нужно поднимать вручную. Вот так вот и теряются целые сервера)

    Reply

Leave a Comment

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