28 декабря 2009 г.

О периодичности нумерации документов и проблемах с уникальностью номеров

Несколько лет назад, когда я только начинал писать на платформе 1С 8 и многое тогда мне было в новинку, я столкнулся с одной проблемой. Я писал конфигурацию с нуля для нужд нашего предприятия. До этого она уже существовала у меня на платформе 1С 7.7. Но очередную версию я решил воссоздать в 1С 8.0, чтобы получить опыт программирования в новой платформе. Задача была мне известна, но в 1С 8 оказалось не все так просто, как могло показаться сначала.

Через некоторое время мне стали поступать звонки от пользователей по одной и той же проблеме: система выдавала ругательное сообщение «Не уникальный номер документа». Анализ ситуации выявил причину некорректной работы документа. Причина крылась в периодичности автонумерации документа.

Когда Вы создаете в конфигураторе документ нового вида, Вы можете назначить периодичность нумерации документа. Как правило, назначается периодичность нумерации «В пределах года». То есть с начала нового года нумерация документов данного вида вновь начинается с единицы. А теперь представьте ситуацию: начало года, но документы набивают «задним числом», то есть в прошлом периоде. Обычная, в общем-то, ситуация. Так вот, когда пользователь создает документ, только что созданному документу присваивается рабочая дата. А рабочая дата - по умолчанию текущая дата. Соответственно номер документа присваивается для текущей даты. Затем пользователь меняет дату нового документа на дату из другого периода и пытается записать. Платформа 1С 7.7 сама распознает такую ситуацию и выдает сообщение «Для документов вида ... каждый год нумерация начинается заново. Присвоить новый номер?». Если нажать кнопку «Да», то документу автоматически присваивается новый номер, соответствующий периоду, и никаких коллизий не возникает. В 1С 8 при смене даты документа никакой реакции системы не происходит, номер документа не меняется. Разработчики платформы решили оставить решение этой ситуации разработчикам конфигураций. И это правильно, я считаю.

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

Перем ТекущаяДатаДокумента;

Процедура ДатаПриИзменении(Элемент)
    Если НачалоГода(ТекущаяДатаДокумента) - НачалоГода(Дата) <> 0 Тогда
        Номер = "";
    КонецЕсли;
    ТекущаяДатаДокумента = Дата;
КонецПроцедуры

Процедура ПриОткрытии()
    ТекущаяДатаДокумента = Дата;
КонецПроцедуры

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

Процедура ПроверитьНомерДокумента(ДокументОбъект, НачальнаяДатаДокумента) Экспорт
    // Определяем назначенную для данного вида документов периодичность смены номера
    ПериодСменыНомера = ДокументОбъект.Метаданные().ПериодичностьНомера;

    //В зависимости от установленной периодичности смены номеров,
    //определяем разность старой и новой датами документа.
    Если ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Год Тогда
        РазностьДат = НачалоГода(НачальнаяДатаДокумента) - НачалоГода(ДокументОбъект.Дата);
    ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Квартал Тогда
        РазностьДат = НачалоКвартала(НачальнаяДатаДокумента) - НачалоКвартала(ДокументОбъект.Дата);
    ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.Месяц Тогда
        РазностьДат = НачалоМесяца(НачальнаяДатаДокумента) - НачалоМесяца(ДокументОбъект.Дата);
    ИначеЕсли ПериодСменыНомера = Метаданные.СвойстваОбъектов.ПериодичностьНомераДокумента.День Тогда
        РазностьДат = НачалоДня(НачальнаяДатаДокумента) - НачалоДня(ДокументОбъект.Дата);
    Иначе
        Возврат;
    КонецЕсли;

    Если РазностьДат <> 0 Тогда
        ДокументОбъект.Номер = "";
    КонецЕсли;
КонецПроцедуры

P. S. Хотите увидеть ссылку на Ваш сайт в конце следующего поста? Пишите письма, а мы рассмотрим!

Комментировать в ВКонтакте

Комментировать в Facebook

Комментировать в Blogger

Комментариев нет:

Отправить комментарий