Приветствую Вас ГостьЧетверг, 16.01.2025, 03:03

Каталог статей


Проведение документов

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

Если каждый документ, формирующий движения в количественном учете, будет проводиться с поддержкой механизма оперативного проведения и движения его будут датироваться именно датой документа, то можно быть уверенным в двух фактах:

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

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

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

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

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

В алгоритмах проведения документов часто используют следующий алгоритм:

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

С оперативным проведением документов связано понятие оперативной отметки времени и понятие момента времени.

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

Оперативная отметка времени создается системой каждый раз при оперативном проведении документа. Ее значение формируется исходя из текущей даты сеанса и последней созданной оперативной отметки.

  • Если последняя оперативная отметка меньше текущей даты сеанса, в качестве новой оперативной отметки принимается текущая дата сеанса.
  • Если последняя оперативная отметка равна или больше текущей даты сеанса, в качестве новой оперативной отметки принимается значение на одну секунду большее, чем старая оперативная отметка времени.

Таким образом, если у объекта конфигурации Документ установлено свойство оперативного проведения, последовательность действий системы будет следующей:

  • при создании нового документа система будет устанавливать ему текущую дату сеанса и «нулевое» время;
  • при проведении такого документа (с датой, день которой соответствует дню текущей даты сеанса) система установит в качестве даты документа оперативную отметку времени.
  • если отменить проведение документа и затем провести его снова (не изменяя даты), система установит документу новую оперативную отметку времени;
  • если попытаться перепровести документ, то система также автоматически установит документу новую оперативную отметку времени и проведет его;
  • при попытке проведения (или перепроведения) оперативно проводимого документа с датой, день которой меньше дня текущей даты сеанса, документ будет проведен неоперативно.
  • если попытаться провести (или перепровести) оперативно проводимый документ с датой, день которой больше дня текущей даты сеанса, то система не даст выполнить такое действие.

Можно получить оперативную метку программно посредством метода ПолучитьОперативнуюОтметкуВремени().

Если в рамках одного дня уже выдана оперативная отметка времени со временем 23:59:59, то следующий оперативно проводимый документ того же дня выдаст пользователю сообщение о невозможности провести данный документ оперативно (в рамках того же дня) – «Дата документа не соответствует текущей дате или дате последнего оперативно проведенного документа. Документ не может быть проведен оперативно!», и проведение документа не состоится

Момент времени

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

МоментВремени() - это момент непосредственно ПЕРЕД позицией документа. (если необходимо получить момент непосредственно после позиции документа, то используйте объект Граница)

Кроме того, момент времени позволяет идентифицировать и необъектные данные, например, записи регистров, подчиненных регистратору.

Понятие момента времени реализовано во встроенном языке при помощи универсального объекта МоментВремени. Этот объект имеет свойства Дата и Ссылка, которые позволяют получить «составляющие» момента времени, и один метод – Сравнить(), при помощи которого возможно сравнение двух моментов времени между собой. Кроме этого, объект МоментВремени имеет конструктор и может быть создан в явном виде для любого объекта базы данных ссылочного типа.

Для нескольких документов, имеющих одинаковую дату и время, последовательность их на оси событий определяется системой исходя из ссылок на эти документы. Она может не совпадать с последовательностью создания документов, и она недоступна для изменения пользователем, то есть нельзя каким-либо образом повлиять на последовательность документов внутри одной секунды или вычислить, что один документ создан раньше, а другой – позже.

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

Использовать режим проведения (Автоматически/Неоперативный/Оперативный/Запрашивать) - определяет способ проведения документа в данной форме, если запись будет инициирована из формы.

  • Автоматически - режим проведения документа система выбирает исходя из даты документа и позиции документа по отношению к оперативной метке и т.д.
  • Запрашивать - перед проведением выдается запрос на то, каким режимом проводить документ. Перед формированием диалога с вопросом система проверяет наличие прав у пользователя на неоперативное проведение документа. Если таких прав нет, то диалог не выходит и выходит соответствующее сообщение об ошибке.
  • Неоперативный - документ проводится всегда неоперативно не зависимо от даты документа.
  • Оперативный - пытается провести документ оперативно. Если дата документа не соответствует требованиям, то выходит ошибка.

Если свойство ИспользоватьРежимПроведения имеет значение Автоматически или Оперативный, и  оперативная метка имеет время = конец дня, то платформа будет пытаться выполнить оперативное проведение документа, что приведет к сообщению об ошибке. 

Пример обработки проведения

Процедура ОбработкаПроведения(Отказ, РежимПроведения)    
    // Укажем движения по каким регистрам нужно записывать. Это надо указать, если у документа "Запись движений при проведении" = "Записывать выбранные".    
    // Это позволяет при проведении записывать всего один раз в конце транзакции. Запись приводит к блокировкам, поэтому чем меньше раз записываем, тем меньше блокировок.

    // автоматически снимается при записи набора данных
    Движения.ТоварыНаСкладах.Записывать = Истина;
    Движения.Продажи.Записывать = Истина;
    
    // Создать менеджер временных таблиц
    МенеджерВТ = Новый МенеджерВременныхТаблиц;
    
    Запрос = Новый Запрос;
    
    // Укажем, какой менеджер временных таблиц использует этот запрос

   //  Сгруппируем данные по номенклатуре на случай наличия в документе нескольких строк с одной номенклатурой
    Запрос.МенеджерВременныхТаблиц = МенеджерВТ;

    Запрос.Текст = 
            "ВЫБРАТЬ
            |    РеализацияТоваровСостав.Номенклатура,
            |    РеализацияТоваровСостав.Номенклатура.Услуга КАК Услуга,
            |    СУММА(РеализацияТоваровСостав.Количество) КАК КоличествоВДокументе,
            |    СУММА(РеализацияТоваровСостав.Сумма) КАК СуммаВДокументе
            |ПОМЕСТИТЬ НоменклатураДокумента
            |ИЗ
            |    Документ.РеализацияТоваров.Состав КАК РеализацияТоваровСостав
            |ГДЕ
            |    РеализацияТоваровСостав.Ссылка = &Ссылка
            |
            |СГРУППИРОВАТЬ ПО
            |    РеализацияТоваровСостав.Номенклатура,
            |    РеализацияТоваровСостав.Номенклатура.Услуга";

    Запрос.УстановитьПараметр("Ссылка", Ссылка);

    Результат = Запрос.Выполнить();

    Запрос2 = Новый Запрос;
    Запрос2.МенеджерВременныхТаблиц = МенеджерВТ;
    Запрос2.Текст = "ВЫБРАТЬ
                    |    НоменклатураДокумента.Номенклатура,
                    |    НоменклатураДокумента.Услуга,
                    |    НоменклатураДокумента.КоличествоВДокументе,
                    |    ЕСТЬNULL(НоменклатураДокумента.СуммаВДокументе, 0) КАК СуммаВДокументе
                    |ИЗ
                    |    НоменклатураДокумента КАК НоменклатураДокумента";
                    
    Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
        // Установим необходимость блокировки данных в регистре ТоварыНаСкладах, чтобы заблокировать чтение остатков другими транзакциями
        Движения.ТоварыНаСкладах.БлокироватьДляИзменения = Истина;
        // Запишем пустые наборы записей чтобы читать остатки без учета данных в документе (на случай перепроведения документа, чтобы удалит прежние движения)
        Движения.ТоварыНаСкладах.Записать();
    КонецЕсли;
    
    Результат = Запрос2.Выполнить();
    
    ВыборкаДетальныеЗаписи = Результат.Выбрать();

    // Запишем движения в регистры
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        
        Если НЕ ВыборкаДетальныеЗаписи.Услуга Тогда
            // Сформировать движения по регистру ТоварыНаСкладах (расход)
            Движение = Движения.ТоварыНаСкладах.Добавить();
            Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
            Движение.Период = Дата;
            Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
            Движение.Склад = Склад;
            Движение.Количество = ВыборкаДетальныеЗаписи.КоличествоВДокументе;
        КонецЕсли;

        // Сформировать движения по регистру Продажи 
        Движение = Движения.Продажи.Добавить();
        Движение.Период = Дата;
        Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
        Движение.Контрагент = Контрагент;
        Движение.Количество = ВыборкаДетальныеЗаписи.КоличествоВДокументе;
        Движение.Сумма = ВыборкаДетальныеЗаписи.СуммаВДокументе;
        Движение.ВидОперации = ВидОперации;
        
    КонецЦикла;

    Движения.Записать();

    Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
        // Проверить отрицательные остатки при оперативном проведении. Остатки получаем без установки периода, так как при оперативном проведении данный момент времени является последним (актуальные итоги). Это ускоряет получение остатков. Если надо будет проверить остатки не в оперативном режиме, то надо использовать период типа Граница(Ссылка, ВидГраницы.Включая);
        Запрос3 = Новый Запрос;
        Запрос3.МенеджерВременныхТаблиц = МенеджерВТ;
        Запрос3.Текст = "ВЫБРАТЬ
                        |    ТоварыНаСкладахОстатки.Номенклатура,
                        |    ТоварыНаСкладахОстатки.КоличествоОстаток
                        |ИЗ
                        |    РегистрНакопления.ТоварыНаСкладах.Остатки(
                        |            ,
                        |            Номенклатура В
                        |                    (ВЫБРАТЬ
                        |                        НоменклатураДокумента.Номенклатура
                        |                    ИЗ
                        |                        НоменклатураДокумента)
                        |                И Склад = &Склад) КАК ТоварыНаСкладахОстатки
                        |ГДЕ
                        |    ТоварыНаСкладахОстатки.КоличествоОстаток < 0";
                        
        Запрос3.УстановитьПараметр("Склад", Склад);
        
        РезультатСНехваткой = Запрос3.Выполнить();
        
        ВыборкаРезультатаСНехваткой = РезультатСНехваткой.Выбрать();
            
        Пока ВыборкаРезультатаСНехваткой.Следующий() Цикл
            Сообщение = Новый СообщениеПользователю();
            Сообщение.Текст = "Не хватает " + Строка(- ВыборкаРезультатаСНехваткой.КоличествоОстаток) + " единиц товара """ + ВыборкаРезультатаСНехваткой.Номенклатура + """ на складе """ + Склад + ".";
            Сообщение.Сообщить();
            Отказ = Истина; // устанавливаем Отказ для отката транзакции (операции в Обработке проведения автоматически выполняются в транзакции)
        КонецЦикла;
    КонецЕсли;
    
КонецПроцедуры

 

 

 

Категория: Программирование | Добавил: leshic (04.02.2022)
Просмотров: 473 | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *:
Вход на сайт
Поиск
Категории раздела
СКД [50]
Регистры [7]
Формы [47]
Администрирование [41]
Запросы [10]
Объекты конфигурации и типы данных [20]
Взаимодействие с другими базами, приложениями и источниками данных [16]
Программирование [41]
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0