Изменение времени документов, перенос документов в начало дня. 1С 7.7

Данная обработка 1С 7.7 помогает, когда кто-то установил точку актуальности на конец текущего дня (провел документ концом дня) и документы перестали проводиться. Теперь, чтобы нормализовать ситуацию, время документов нужно изменить и документы перепровести, затем перенести точку актуальности на последний проведенный документ.

Запускать обработку надо монопольно. При нажатии "Сформировать" все документы будут перенесены на начало дня (начиная с указанной  в модуле даты с сохранением последовательности и интервалом 1 секунда).

 

 Техническая реализация переноса времени на начало дня

Обработка написана в комплексной конфигурации 4.2 (7.70.424). Версия платформы 7.70.027.

 

20 Comments

  1. CheBurator

    наращивание времени как сделано? что суммируется? как сделан переход на минутах и часах?

    примечание боковое: по 10 секунд в общем случае — «плохо».

    надо смотреть в каком времени первый непереносимый документ и впихивать переносимые ДО этого документа. соответсвенно надо посчитать дельту наращивани времени.

    Reply
  2. ksnik

    (1) я открыл код, пересчет прямой: время=ЧЧ*60*60+ММ*60+СС и обратный к нему.

    надо смотреть в каком времени первый непереносимый документ и впихивать переносимые ДО этого документа

    это зачем? оно же изменит последовательность проведения документов?

    Reply
  3. sanek_kop

    Если база SQL, то я бы посоветовал использовать 1C++ и писать напрямую в необходимые таблицы. На практике это экономит достаточно много времени. В условиях когда работа предприятия встала, время работы — очень важный параметр. Изначально делали примерно так же как в этой обработке, только выбирали последний правильный документ (с верным временем) и перепроведение делали с интервалом в 1 секунду. После того как переписали на SQL длительность обработки с 15-20 минут уменьшилось до 5-10. Причем львиную долю. времени занимает установка ТА.

    Reply
  4. ksnik

    (3) вариант с 1C++ менее универсален так как для его реализации не достаточно функционала 1С. А код обработки можете написать сюда?

    Reply
  5. CheBurator

    (2) для переноса документов «в начало дня» — все переносимые «в начало дня» документы в общем случае должны быть ДО первого неперносимого документа.

    .

    По наращиванию времени — я так и знал!!!

    (смотри у меня публикацию пр финт ушами с временем документа).

    Для переноса достаточно оперировать только СС, если секунды задашь больше 60 — платформа это правильно проглотит сама. это работает в пределах дня, дальше 23.59-59 или 00-00-00 не уйдет документ сколько бы большое значение СС ни было. Пользуйся!

    Reply
  6. CheBurator

    Если через 1С++ чистить нудевые записи в итогах таблицы то перенос ТА идет быстро на границе месяцев.

    Reply
  7. ksnik

    (5) багофичи это зло ибо делает код черезжопным, в моей программе ошибок нет.

    Я указал на то что перенос документа через документ ломает логику взаиморасчетов.

    Reply
  8. CheBurator

    (7) багофичи — на вкус и цвет, согласен.

    Reply
  9. CheBurator

    (7)

    Я указал на то что перенос документа через документ ломает логику взаиморасчетов.

    уу, название ппубликации вводит в заблуждение. поправить бы хорошо.

    потому что перенос документов в начало дня — это перенос в начало дня.

    здесь по факту перенос ВСЕХ (это ключевой момент) документов, лежащих после времени «Ч» до конца дня — в «правильную» последовательность документов ПОСЛЕ «Ч». Конечно, а таком контексте выполнения задачи, мое замечание неверно.

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

    Последнее правильное время=14 сек (Док0). Считаем что все проведение было сделано правильно, ГП не нарушена.

    Исходная цепочка:

    Док1, 15 сек

    Док2, 15 сек

    Док3, 16 сек

    Док4, 16 сек

    По идее, после обработки (сдвиг по 1 сек на документ) получится так:

    Док1, 15 сек (14+1), ОК

    Док2, 16 сек (14+2) — конфликт с Док3, Док2 ляжет и проведется ПОСЛЕ ЕЩЕ НЕ ОБРАБОТАННОГО Док3 (другой результат проведения получится чем до переноса) и не факт что Док2 проведется вообще

    Док3, 17 сек (14+3) — конфликт с Док4, Док3 ляжет и проведется ПОСЛЕ ЕЩЕ НЕ ОБРАБОТАННОГО Док4 (другой результат проведения получится чем до переноса) и вдобавок проведение док3 будет опираться на неверные результаты проведения Док2 и не факт что Док3 проведется вообще

    Док4, 18 сек (14+4) — проведение док4 будет опираться на неверные результаты проведения Док2 и Док3 и не факт что Док4 проведется вообще.

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

    Для получения гарантированного правильного результата следует ОБЯЗАТЕЛЬНО восстановить ГП последовательность документов от Док0 до последнего перенесенного документа. Или переписать алгоритм переноса.

    Reply
  10. CheBurator

    (7) Имхо

    В данном коде обертывать обработку единственного документа В МОНОПОЛЬНОМ Режиме — совершенно излишне. В приведенном коде при любой ошибке — выполнение стопорится (логику по крайне мере такую я наблюдаю).

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

    Итого: транзакции если убрать и оставить только попытку — ничего в логике не поменяется.

    ?

    Reply
  11. CheBurator

    (7) Не уверен, точно не помню, но что-то так:

    Выполнение Док.Провести() вообще сомнительно в таком применении.

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

    А вот если проведение просто НЕ ПРОВЕДЕТСЯ о вернет результат проведения — 0 (штатно как обычно установкой статусвозврата(0) — никакое исключение не произойдет. Поэтому надо типа внутри попытки

    Результат = Док.Провести();

    Если Результат =0 Тогда

    //искуственно вызвать исключение или прерваться явно

    Reply
  12. ksnik

    (9) Сергей, спасибо за подробное объяснение принципа действия алгоритма. На самом деле алгоритм рабочий, переписывать его не надо. Но Ваша постановка задачи к которой Вы применили алгоритм не имеет смысла. Никто не переносит документы на секунду назад, 100 % случаев возникает необходимость перенести на несколько часов, поэтому описанная Вами ситуация практически не возможна.

    Док3 (другой результат проведения получится чем до переноса) и не факт что Док2 проведется вообще

    На самом деле практические задачи для решения которых мной предназначен алгоритм в публикации такие:

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

    2) алгоритм поможет если надо перенести документы на начало дня, хоть на 00 часов — не ломая последовательности.

    3) алгоритм поможет, когда кто-то установил точку актуальности на конец текущего дня (провел документ концом дня) и документы перестали проводиться. Теперь, чтобы нормализовать ситуацию, время документов нужно изменить и документы перепровести, затем перенести точку актуальности на последний проведенный документ. Решать эту задачу в разделенном режиме смысла нет, так как в разделенном режиме пользователи напрасно будут мучать базу — все равно документы не проводятся, да и точку актуальности на последний документ можно установить только в монопольном режиме.

    Reply
  13. CheBurator

    (12) все пункты работают только если верить что » 100 % случаев возникает необходимость перенести на несколько часов, поэтому описанная Вами ситуация практически не возможна.»

    — практически не очень вероятно, да. но вполне может случится казус.

    ибо в приведенном примере — алгоритм породит некорректные данные.

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

    в общем случае — алгоритм нерабочий. да, я тоже оцениваю вероятность трабла как маленькую.

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

    .

    транзакция в коде — как у вас — излишняя.

    И что главное — Док.Провести() — в случае непроведения НЕ ВЫЗОВЕТ ИСКЛЮЧЕНИЯ. что может в такой (или разновидностях такой логики обработки чуть более сложной) привести к ЯВНОЙ ОШИБКЕ в итогах переноса.

    .

    та позже, в вашем коде, в случае если Док.Провести() не проведется — скорее всего упадет на ЗафиксироватьТранзакцию(), ибо транзакция уже отатана назад неявно.

    Reply
  14. ksnik

    (13) Спасибо за подробное замечание!!

    Док.Провести() — в случае непроведения НЕ ВЫЗОВЕТ ИСКЛЮЧЕНИЯ

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

      Если Провед=1 Тогда
    Если Док.Провести()=0 Тогда
    ф = 1/0;
    КонецЕсли;
    Иначе
    Док.Записать();
    КонецЕсли;
    

    но практически это пока не испробовано. Ну ни разу у меня не было проблем с этим, возможно причина в СтатусВозврата(0)+транзакции, надо провести тест…

    Reply
  15. ksnik

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

    1)В тестовой базе берем любой документ, в начале обработки проведения пишем:

    Процедура ОбработкаПроведения()
    Если Сумма > 0 Тогда
    СтатусВозврата(0);
    Возврат;
    КонецЕсли;
    …
    КонецПроцедуры 

    Я для примера в документ Аккредитив добавил, установил признак проводить в оперативном учете. Реструктуризация прошла…

    2)создаем и проводим с нулевой суммой

    3)редактируем реквизит сумма = 1р

    4) запускаем мою обработку

    Смотрим результат, попробуйте повторить сами:

    1
    Документ не проведен! :Аккредитив АкСцНС000001 (09.10.2019)
    ЗафиксироватьТранзакцию();
    {\путькобработкеПЕРЕНОС ДОКУМЕНТОВ ВНАЧАЛО ДНЯ.ERT(64)}: Ошибка при выполнении процедуры ЗафиксироватьТранзакцию
    Reply
  16. CheBurator

    (15) все правильно, я об этом и сказал выше, что сломается на ЗафиксироватьТранзакцию.

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

    это я к тому, что надо помнить что неудачное проведение не вызывает исключения.

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

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

    Если Док.Провести()=0 Тогда Прервать; КонецЕсли;

    .

    По большому счету — эти мои замечания про Провести() — относятся больше к общему подходу к программированию в части правильности написания кода.

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

    Пусть код так и будет.

    Reply
  17. ksnik

    (16) У меня есть практический совет о «прервать» применительно к обработкам документов. Если требуется однозначно прекратить выполнение кода (вот как например требуется в данном случае) я всегда вместо «Прервать» пишу «ф = 1/0;», это красивее выглядит. Ато дальше после «Прервать» может что-нибудь нехорошее произойти.

    п.с. У меня ведь тоже багофича получиласть, поэтому код статьи и обработку поправлю после удачного применения нового алгоритма на практике.

    Reply
  18. ksnik

    (13)

    транзакция в коде — как у вас — излишняя.

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

    Reply
  19. ksnik

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

    Reply
  20. ksnik

    (10)

    надо продумать что будет при исправлении допустим ошибки непроведения и повторном запуске обработки).

    Итого: транзакции если убрать и оставить только попытку — ничего в логике не поменяется.

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

    Если транзакцию убрать, произойдут необратимые изменения, которые потом надо будет исправлять, тратить на это время.

    Reply

Leave a Comment

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