1С специалист по платформе

(7)суть сторнирования в расчете зарплаты при начислении её:

Процедура ОбработкаПроведения(Отказ, Режим) Для Каждого ТекСтрокаСписок Из Список Цикл Дата1 = НачалоДня( ТекСтрокаСписок.ДатаНачала ); Дата2 = КонецДня( ТекСтрокаСписок.ДатаОкончания ); // регистр Расчеты Движение = Движения.Расчеты.Добавить(); Движение.Сторно = Ложь; Движение.ВидРасчета = ТекСтрокаСписок.ВидРасчета; Движение.ПериодДействияНачало = Дата1; Движение.ПериодДействияКонец = Дата2; Движение.ПериодРегистрации = ПериодРегистрации; Движение.БазовыйПериодНачало = Дата1; Движение.БазовыйПериодКонец = Дата2; Движение.Сотрудник = ТекСтрокаСписок.Сотрудник; Движение.Подразделение = ТекСтрокаСписок.Подразделение; Движение.Должность = ТекСтрокаСписок.Должность; Движение.Результат = 0; Движение.Данные = ТекСтрокаСписок.Размер; Движение.График = ТекСтрокаСписок.График; КонецЦикла; // для того чтобы получить дополнение требуется записать движения Движения.Расчеты.Записать(); // Обработка дополнения, если оно возникло Дополнение = Движения.Расчеты.ПолучитьДополнение(); Если Дополнение.Количество() > 0 Тогда // визуальный контроль таблицы дополнения Дополнение.ВыбратьСтроку(«Просмотр записей дополнения»); Для каждого СтрокаДоп Из Дополнение Цикл // регистр Расчеты Движение = Движения.Расчеты.Добавить(); Движение.Сторно = Истина;// вносим сторно — запись ! Движение.ВидРасчета = СтрокаДоп.ВидРасчета; Движение.ПериодДействияНачало = СтрокаДоп.ПериодДействияНачалоСторно; Движение.ПериодДействияКонец = СтрокаДоп.ПериодДействияКонецСторно; Движение.ПериодРегистрации = СтрокаДоп.ПериодРегистрацииСторно; Движение.БазовыйПериодНачало = СтрокаДоп.БазовыйПериодНачало; Движение.БазовыйПериодКонец = СтрокаДоп.БазовыйПериодКонец; Движение.Сотрудник = СтрокаДоп.Сотрудник; Движение.Подразделение = СтрокаДоп.Подразделение; Движение.Должность = СтрокаДоп.Должность; Движение.Результат = 0; Движение.Данные = СтрокаДоп.Данные * (-1); Движение.График = СтрокаДоп.График; КонецЦикла; // записываем движения регистров с движениями дополнения Движения.Расчеты.Записать(); КонецЕсли; // Расчитать оклад ВыполнитьРасчетНачислений( Движения.Расчеты, ПланыВидовРасчета.Основной.Оклад ); Движения.Расчеты.Записать( , Истина ); // Расчитать больничный ВыполнитьРасчетНачислений( Движения.Расчеты, ПланыВидовРасчета.Основной.Больничный ); Движения.Расчеты.Записать( , Истина ); КонецПроцедуры

О чем эта статья

В статье рассказывается об использовании конструкции «ДЛЯ ИЗМЕНЕНИЯ” языка запросов 1С. Данный материал будет особенно полезен тем, кто хочет разобраться с особенностями блокировок регистров при работе с информационной базой в варианте клиент-сервер.

Применимость

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

Конструкция ДЛЯ ИЗМЕНЕНИЯ

При использовании автоматического режима блокировок чтение без опции ДЛЯ ИЗМЕНЕНИЯ и последующая запись в рамках одной транзакции может приводить к возникновению взаимоблокировок, вызванных использованием недостаточного уровня блокировки ресурса.

Конструкция ДЛЯ ИЗМЕНЕНИЯ используется, чтобы вместо разделяемой S-блокировки установить U-блокировку обновления, совместимость которой с другими блокировками хуже:

В таблице стоит знак «+», если блокировки на пересечении строки и столбца совместимы, «–» – в противном случае.

Рассмотрим кратко основные виды блокировок.

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

Блокировки обновления (U) предотвращают возникновение распространенной формы взаимоблокировки. В сериализуемой транзакции или транзакции с повторяющимся чтением транзакция считывает данные, запрашивает разделяемую (S) блокировку на ресурс, затем выполняет изменение данных, что требует преобразование блокировки в исключительную (X).

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

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

Начнется ожидание блокировки.

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

Чтобы избежать этой потенциальной взаимоблокировки, применяются блокировки обновления (U). Блокировку обновления (U) может устанавливать для ресурса одновременно только одна транзакция. Если транзакция изменяет ресурс, то блокировка обновления (U) преобразуется в исключительную (X) блокировку.

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

Конструкция ДЛЯ ИЗМЕНЕНИЯ указывается в конструкторе запроса на закладке Дополнительно:

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

В управляемом режиме блокировок описываемой проблемы не существует, поэтому конструкция ДЛЯ ИЗМЕНЕНИЯ ни на что не влияет.

PDF-версия статьи для участников группы ВКонтакте

Мы ведем группу ВКонтакте – http://vk.com/kursypo1c.

Если Вы еще не вступили в группу – сделайте это сейчас и в блоке ниже (на этой странице) появятся ссылка на скачивание материалов.

Если Вы уже участник группы – нужно просто повторно авторизоваться в ВКонтакте, чтобы скрипт Вас узнал. В случае проблем решение стандартное: очистить кеш браузера или подписаться через другой браузер.

+7(495)688-90-02, spec@1c.ru,

До особого указания экзамены проводятся в дистанционном формате (если в городе/регионе введен режим самоизоляции). Обращайтесь в центры сертификации вашего города https://1c.ru/spec/default.jsp. Допускается сдавать экзамены в экзаменационном центре другого города, если в вашем городе не проводят дистанционную сдачу. Так же можно обращаться в 1С:Учебный центр №1 в Москве https://1c.ru/uc1. По вопросам можно писать на spec@1c.ru

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

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

Первый этап подготовки: получить сертификат «1С:Профессионал». Перед каждым «1С:Специалистом» есть экзамен-допуск — «1С:Профессионал», т.е. если Вы планируете сдавать экзамен «1С:Специалист» по программе «1С:Бухгалтерия», то Вам предварительно нужно получить сертификат «1С:Профессионал» по программе «1С:Бухгалтерия 8» или программе «1С:Управление производственным предприятием 8». Экзамен «1С:Профессионал» — это тест, из 14 вопросов теста нужно верно ответить минимум на 12. К «1С:Профессионалу», как и к любому другому экзамену нужно обязательно готовиться, без подготовки его сдать очень трудно. Подробно о подготовке к экзамену «1С:Профессионал» можно почитать на сайте фирмы «1С» в разделе «Курсы 1С / Экзамены 1С / 1С:Профессионал /Подготовка к тестированию».

После того, как у Вас будет на руках сертификат «1С:Профессионал», Вы получаете допуск на экзамен «1С:Специалист». Однако это не значит, что нужно сразу идти его сдавать. Вы лишь начали подготовку. Если Вы заинтересованы в результате, нужно продолжать готовиться.

Существует три способа подготовки к экзамену «1С:Специалист»:

  1. пройти курсы обучения;
  2. изучить методическую литературу;
  3. накопить личный опыт работы по настройке и адаптации программ.

В идеале, способы нужно комбинировать. Рассмотрим подробно каждый из них.

Курсы обучения

Выбору курсов на начальном этапе подготовки посвящена отдельная статья «Как выбрать обучающий курс 1С».

Курсы наиболее предпочтительны для подготовки к экзамену:

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

Для подготовки к экзамену «1С:Специалист» по платформе рекомендуются следующие курсы 1С:

  1. Комплексный курс «Конфигурирование в системе «1С:Предприятие 8» в ЦСО;
  2. «Конфигурирование платформы «1С:Предприятие 8» в 1С:Учебном центре № 1.

Рекомендуем курсы углубленного изучения платформы по темам, в которых у Вас есть пробелы:

  1. Механизм системы компоновки данных в платформе «1С:Предприятие 8»;
  2. Механизм бизнес-процессов в платформе «1С:Предприятие 8»;
  3. Анализ данных и прогнозирование средствами платформы «1С:Предприятия 8»;
  4. Работа с формами в «1С:Предприятии 8»;
  5. Средства интеграции и обмена данными в системе «1С:Предприятие 8»;
  6. Использование запросов в системе «1С:Предприятие 8».

Для подготовки к экзамену «1С:Специалист» по прикладным решениям рекомендуются следующие курсы 1С:

  1. «1С:Предприятие 8». Внедрение и адаптация конфигурации «Бухгалтерия предприятия» (конфигурирование в типовом решении) в ЦСО или аналогичный курс в 1С:Учебном центре № 1;
  2. «1С:Предприятие 8». Внедрение и адаптация прикладного решения «1С:Управление торговлей 8» в ЦСО;
  3. «1С:Предприятие 8». Внедрение и адаптация конфигурации «Зарплата и Управление Персоналом» в ЦСО или Конфигурирование подсистем расчета зарплаты и управления персоналом в прикладных решениях для «1С:Предприятия 8» в 1С:Учебном центре № 1.

Для подготовки к экзамену «1С:Специалист-консультант» по прикладным решениям рекомендуются следующие курсы 1С:

  1. Внедрение прикладного решения «1С:Бухгалтерия 8» версии ПРОФ (ред.3.0) в 1С:Учебном центре №1
  2. Внедрение прикладного решения «1С:Управление торговлей 8» в 1С:Учебном центре №1
  3. Внедрение прикладного решения «1С:Зарплата и управление персоналом 8» в 1С:Учебном центре №1

Методическая литература

Методическая литература является прекрасным дополнением к курсам обучения. Полный перечень литературы всегда доступен на v8.1c.ru.

Самостоятельная работа

На курсах и в книгах Вы изучите методы работы с программой. Эти методы требуется не только изучить в теории, но и научиться использовать на практике. Поэтому хорошим дополнением при подготовке к экзамену будет самостоятельная работа, практика. Чаще всего, молодых, начинающих специалистов к самостоятельной работе не допускают, специально на этот случай подготовлен Сборник задач для подготовки к экзамену «1С:Специалист» по платформе «1С:Предприятие 8». Примерно так выглядят задачи в реальной деятельности, из них же компонуются билеты на экзамене. На экзамен имеет смысл идти только тогда, когда задачи сборника не вызывают серьезных затруднений, когда они прорешаны. Решение желательно обсудить с опытным специалистом, работающим вместе с вами на предприятии (с человеком, у которого уже есть сертификат). Если такого специалиста нет, то рекомендуется пройти курс «Консультация к экзамену «1С:Специалист» по платформе «1С:Предприятие 8.3» в 1С:Учебном центре № 1.

Примеры билетов по всем экзаменам также выложены на нашем сайте.

Теги: 1С:Предприятие • Движения • Документ • МоментВремени • ОбработкаПроведения

Когда происходит интерактивное или программное проведение документа, срабатывает выполнение процедуры ОбработкаПроведения(), которая находится в модуле объекта документа.

Процедура ОбработкаПроведения(Отказ, РежимПроведения) // Вставить содержимое обработчика КонецПроцедуры

Данная процедура имеет два параметра: Отказ и РежимПроведения. Если выставить параметру Отказ значение Истина, то проведение не будет выполнено. Параметр РежимПроведения устанавливает режим проведения документа — «оперативное» или «неоперативное». Сами движения в регистры разработчик должен прописать в этой процедуре самостоятельно.

Рассмотрим подробно свойства документа на вкладке «Движения»

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

Процедура ОбработкаПроведения

Формирование новых наборов записей регистров включает в себя операции, состоящие:

  • из добавления новых записей к набору записей;
  • заполнения полей записей;
  • записи набора записей.

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

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

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

Следует учитывать, что при автоматической записи движений они будут записаны с замещением, то есть старые движения документа будут замещены новыми. Фактически, платформа неявно выполнит код:

// По умолчанию параметр Замещать имеет значение Истина Движения.ТоварыНаСкладах.Записать();

Если же при записи движений документа нужно добавлять новые движения к старым, то для этого нужно использовать параметр Замещать, установленным в значение Ложь.

// Добавлять новые движения к старым Движения.ТоварыНаСкладах.Записать(Ложь);

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

Подробнее о формировании движений

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

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

Если разработчик захочет реализовать нестандартный вариант проведения документа и установит свойство «Удаление движений» в значение «Удалять автоматически», то при записи документа с проведением сначала будут удалены все старые движения документа. То есть на момент выполнения обработчика события ОбработкаПроведения в регистрах не будет наборов записей с движениями данного документа.

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

  • Во-первых, если наборы записей необходимо записывать с добавлением, то это нужно выполнять в явном виде, т. к. при автоматической записи движений они будут записаны с замещением.
  • Во-вторых, последовательность обращения к регистрам при автоматической записи движений будет одна и та же для разных документов. Это позволяет снизить вероятность взаимных блокировок при проведении документа в конкурентных режимах работы.

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

Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный);

Пример перепроведения документов РеализацияТоваров в интервале с ДатаНачала по ДатаОкончания:

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

Здесь инициировалось проведение в неоперативном режиме. Значение по умолчанию параметра РежимПроведения метода объекта документа Записать() — именно РежимПроведенияДокумента.Неоперативный.

Оперативное и неоперативное проведение

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

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

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

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

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

Понятие момента времени

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

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

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

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

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

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

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

Поиск: 1С:Предприятие • Движения • Документ • Момент времени • Обработка проведения

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

1. В свойствах конфигурации режим управления блокировками намеренно установлен в автоматический, хотя нужно управляемый. Это необходимо исправить сразу, т.к. по мере решения вы можете насоздавать объектов с неверно установленным режимом управления блокировками, чем позже вы это заметите, тем больше потом исправлять. А если не заметите вовсе, могут «штрафануть».

2. Запустите хотя бы раз синтакс помощник. Компы там не шибко мощные, и если СП ни разу не запускался с момента установки/обновления 1С, его индексация занимает время.

3. В настройках конфигуратора заранее зайдите в Сервис — Параметры и поставьте там «Управляемое приложение и обычное приложение». Это позволит быстро, когда это необходимо, запускать на исполнение конфигурацию в обычном режиме. В обычном режиме доступна консоль запросов. К этому пункту можно так же добавить, что в сети валяется управляемая консоль запросов, которую можно найти обычным поиском и перетащить себе на комп.

4. Создайте сразу подсистемы, этим вы сделаете часть работы которую делать нужно все равно обязательно, однако наглядный интерфейс даже во время разработки упростит вам тестирование. Причем для оптимизации времени, как вариант, можно делать так: создаете подсистему ОперативныйУчет, далее в ней три подсистемы Документы, СправочникиИПланы, Регистры. После этого подсистему ОперативныйУчет раскопируйте еще на две (подчиненные тоже скопируются) и переименуйте в БухгалтерскийУчет и Расчет.

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

ОПЕРАТИВНЫЙ УЧЕТ

6. Новая методика проведения документов. Используется в небольшом проценте задач, однако если попадется, не перемудрите с блокировками, тут ее надо устанавливать при помощи свойства БлокироватьДляИзменения, так же важно включить движения самого документа в запрос по отлову минусов. Пример ниже:

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

7. Правильный порядок расположения операндов при расчете себестоимости. Проблема копеек. Есть мнение, что правильно делать так:

НоваяЗапись.Сумма = Выборка.КоличествоДокумент * Выборка.СуммаОстаток / Выборка.КоличествоОстаток;

То есть, умножение идет перед делением, что обеспечит в случае 3 * 10 / 3 число 10 а не число 9.99999999(9), как может быть при совсем неправильном порядке, однако методически такой способ не считается верным (это слова преподавателя из 1С), во-первых, деление по методике должно идти сначала, но деление не суммы на остаток количества, а количества к списанию на количество остатка, во-вторых, при равенстве количеств, лучше просто взять сумму, поэтому делая так, как ниже, проблем быть не должно:

НоваяЗапись.Сумма = ?(Выборка.КоличествоДокумент = Выборка.КоличествоОстаток, Выборка.СуммаОстаток,
Окр(Выборка.КоличествоДокумент / Выборка.КоличествоОстаток,2) * Выборка.СуммаОстаток);

8. Правильная установка момента времени в качестве параметра запроса при проведении документа. Если документ по вашему решению может проводиться оперативно, то установку параметра для запроса оптимальнее делать так:

Запрос.УстановитьПараметр(«МоментВремени», ?(РежимПроведения=РежимПроведенияДокумента.Оперативный,
Неопределено, МоментВремени()));

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

Движения.ОстаткиНоменклатуры.Записать(); Движения.Продажи.Записать(); Движения.ОстаткиНоменклатуры.Записывать = Истина; Движения.Продажи.Записывать = Истина; // ТУТ НЕОБХОДИМА УПРАВЛЯЕМАЯ БЛОКИРОВКА Запрос = Новый Запрос; Запрос.УстановитьПараметр(«Ссылка», Ссылка); Запрос.УстановитьПараметр(«Момент», ?(РежимПроведения=РежимПроведенияДокумента.Оперативный, Неопределено, МоментВремени())); Запрос.Текст = «ВЫБРАТЬ |РасходнаяНакладнаяСписокНоменклатуры.Номенклатура, |СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество, |СУММА(РасходнаяНакладнаяСписокНоменклатуры.Сумма) КАК Сумма |ПОМЕСТИТЬ втТаблицаДокумента |ИЗ |Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры |ГДЕ |РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка | |СГРУППИРОВАТЬ ПО |РасходнаяНакладнаяСписокНоменклатуры.Номенклатура |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ |втТаблицаДокумента.Номенклатура КАК Номенклатура, |ОстаткиНоменклатурыОстатки.Партия, |ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток, |ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК СуммаОстаток, |втТаблицаДокумента.Количество КАК КоличествоДокумент, |втТаблицаДокумента.Сумма КАК СуммаДокумент, |втТаблицаДокумента.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры |ИЗ |втТаблицаДокумента КАК втТаблицаДокумента |ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки( |&Момент, |Номенклатура В |(ВЫБРАТЬ |втТаблицаДокумента.Номенклатура |ИЗ |втТаблицаДокумента КАК втТаблицаДокумента)) КАК ОстаткиНоменклатурыОстатки |ПО втТаблицаДокумента.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура | |УПОРЯДОЧИТЬ ПО |ОстаткиНоменклатурыОстатки.Партия.МоментВремени |ИТОГИ |СУММА(КоличествоОстаток), |СУММА(СуммаОстаток), |МАКСИМУМ(КоличествоДокумент), |МАКСИМУМ(СуммаДокумент) |ПО |Номенклатура»; Если РегистрыСведений.НастройкаУчетнойПолитики.ПолучитьПоследнее(Дата).УчетнаяПолитика = Перечисления.УчетнаяПолитика.ЛИФО Тогда Запрос.Текст = СтрЗаменить(Запрос.Текст,»ОстаткиНоменклатурыОстатки.Партия.МоментВремени»,

«ОстаткиНоменклатурыОстатки.Партия.МоментВремени УБЫВ»); КонецЕсли; ВыборкаНоменклатура = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам,»Номенклатура»); Пока ВыборкаНоменклатура.Следующий() Цикл Себестоимость = 0; Если ВыборкаНоменклатура.ВидНоменклатуры = Перечисления.ВидыНоменклатуры.Товар Тогда КоличествоСписать = ВыборкаНоменклатура.КоличествоДокумент; Если ВыборкаНоменклатура.КоличествоДокумент > ВыборкаНоменклатура.КоличествоОстаток Тогда Отказ = Истина; // Оповестить о нехватке. Продолжить; КонецЕсли; ВыборкаПартии = ВыборкаНоменклатура.Выбрать(); Пока КоличествоСписать > 0 И ВыборкаПартии.Следующий() Цикл НоваяЗапись = Движения.ОстаткиНоменклатуры.ДобавитьРасход(); НоваяЗапись.Период = Дата; НоваяЗапись.Номенклатура = ВыборкаНоменклатура.Номенклатура; НоваяЗапись.Партия = ВыборкаПартии.Партия; НоваяЗапись.Количество = Мин(КоличествоСписать, ВыборкаПартии.КоличествоОстаток); НоваяЗапись.Сумма = ?(ВыборкаПартии.КоличествоОстаток=НоваяЗапись.Количество,ВыборкаПартии.СуммаОстаток,
Окр(НоваяЗапись.Количество/ВыборкаПартии.КоличествоОстаток,2)*ВыборкаПартии.СуммаОстаток); КоличествоСписать = КоличествоСписать — НоваяЗапись.Количество; Себестоимость = Себестоимость + НоваяЗапись.Сумма; КонецЦикла; КонецЕсли; НоваяЗапись = Движения.Продажи.Добавить(); НоваяЗапись.Период = Дата; НоваяЗапись.Номенклатура = ВыборкаНоменклатура.Номенклатура; НоваяЗапись.Количество = ВыборкаНоменклатура.КоличествоДокумент; НоваяЗапись.Сумма = ВыборкаНоменклатура.СуммаДокумент; НоваяЗапись.Себестоимость = Себестоимость; КонецЦикла;

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

Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить(«РегистрНакопления.ОстаткиНоменклатуры»); ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры; ЭлементБлокировки.ИспользоватьИзИсточникаДанных(«Номенклатура», «Номенклатура»); Блокировка.Заблокировать();

БУХГАЛТЕРСКИЙ УЧЕТ

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

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Проводки = Движения.Управленческий; Проводки.Записывать = Истина; Если НЕ Проводки.Модифицированность() И НЕ ЭтоНовый() Тогда Проводки.Прочитать(); КонецЕсли; Для каждого Проводка Из Проводки Цикл Проводка.Период = Дата; Если НЕ ЭтоНовый() И ПометкаУдаления <> Ссылка.ПометкаУдаления Тогда Проводка.Активность = НЕ ПометкаУдаления; КонецЕсли; КонецЦикла; КонецПроцедуры

12. Управляемая транзакционная блокировка регистра бухгалтерии.

Блокировка = Новый БлокировкаДанных; ЭлементБлокировки = Блокировка.Добавить(«РегистрБухгалтерии.Управленческий»); ЭлементБлокировки.УстановитьЗначение(«Счет», ПланыСчетов.Управленческий.Товары); ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры; ЭлементБлокировки.ИспользоватьИзИсточникаДанных(ПланыВидовХарактеристик.ВидыСубконто.Номенклатура, «Номенклатура»); Блокировка.Заблокировать();

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

| КорСчет В (Значение(ПланСчетов.Управленческий.Поставщики), Значение(ПланСчетов.Управленческий.ПрибылиУбытки))

ПЕРИОДИЧЕСКИЕ РАСЧЕТЫ

14. Самое главное, это правильная организация процедуры расчета записей. Во-первых, желательно ей быть в общем модуле. И не только потому, что он выполняется на сервере, а потому, что это более универсально, чем в модуле конкретного документа. Во-вторых, желательно найти «золотую середину» при получении данных для расчета, с одной стороны неправильно получить одним махом все все данные для всего набора записей, и дальше в одном цикле делать расчет, с другой стороны — получать для каждой записи набора — избыточно. Вариант такой золотой середины ниже, данные получаются по принципу «один запрос на каждый вид расчета»:

Процедура ПроизвестиРасчетНабора(НаборЗаписей) Экспорт Регистратор = НаборЗаписей.Отбор.Регистратор.Значение; Измерения = Новый Массив; Измерения.Добавить(«Сотрудник»); Измерения.Добавить(«Подразделение»); Запрос = Новый Запрос; Запрос.УстановитьПараметр(«Регистратор», Регистратор); Запрос.УстановитьПараметр(«Измерения», Измерения); /////////////////////////////// // ПОВТОРЯЕМЫЙ БЛОК ВидРасчета = ПланыВидовРасчета.ОсновныеНачисления.Оклад; Если НаборЗаписей.ПроверитьНаличиеВидаРасчета(ВидРасчета) Тогда Запрос.УстановитьПараметр(«ВидРасчета», ВидРасчета); Запрос.Текст = «»; // ТЕКСТ ЗАПРОСА ДЛЯ КОНКРЕТНОГО ВИДА РАСЧЕТА Выборка = Запрос.Выполнить().Выбрать(); Для каждого Запись Из НаборЗаписей Цикл Если Запись.ВидРасчета <> ВидРасчета Тогда Продолжить; КонецЕсли; Выборка.Сбросить(); Если Выборка.НайтиСледующий(Запись.НомерСтроки, «НомерСтроки») Тогда Запись.Результат = 0; // ФОРМУЛА ДЛЯ РАСЧЕТА КонецЕсли; КонецЦикла; КонецЕсли; /////////////////////////////// НаборЗаписей.Записать(, Истина); // ПОВТОРЯЕМЫЙ БЛОК НаборЗаписей.Записать(, Истина); // ПОВТОРЯЕМЫЙ БЛОК НаборЗаписей.Записать(, Истина); КонецПроцедуры

Функцию «ПроверитьНаличиеВидаРасчета» имеет смысл разместить в каждом регистре в модуле набора записей. Тогда повторяемые блоки будут универсальными. Сама функция имеет следующий вид:

Функция ПроверитьНаличиеВидаРасчета(ВидРасчета) Экспорт Возврат ?(ЭтотОбъект.ВыгрузитьКолонку(«ВидРасчета»).Найти(ВидРасчета)=Неопределено,Ложь,Истина); КонецФункции

15. Заполнение сторно записей для набора записей регистра расчета.

ТаблицаДополнений = Движения.ОсновныеНачисления.ПолучитьДополнение(); Для каждого ЗаписьСторно Из ТаблицаДополнений Цикл Движение = Движения.ОсновныеНачисления.Добавить(); ЗаполнитьЗначенияСвойств(Движение, ЗаписьСторно); Движение.ПериодРегистрации = ЗаписьСторно.ПериодРегистрацииСторно; Движение.ПериодДействияНачало = ЗаписьСторно.ПериодДействияНачалоСторно; Движение.ПериодДействияКонец = ЗаписьСторно.ПериодДействияКонецСторно; Движение.Сторно = Истина; КонецЦикла;

16. Разбитие оклада при многократном изменении его значения внутри периода расчета. Вариант получения разбивки прямо в запросе.

Запрос = Новый Запрос; Запрос.УстановитьПараметр(«Ссылка», Ссылка); Запрос.УстановитьПараметр(«ДатаНачала», НачалоМесяца(ПериодРегистрации)); Запрос.УстановитьПараметр(«ДатаОкончания», КонецМесяца(ПериодРегистрации)); Запрос.Текст = «ВЫБРАТЬ | ВложенныйЗапрос.Период, | ВложенныйЗапрос.Сотрудник, | ВложенныйЗапрос.Подразделение, | ВложенныйЗапрос.Оклад |ПОМЕСТИТЬ втИзмененияОклада |ИЗ | (ВЫБРАТЬ | СведенияОСотрудникахСрезПоследних.Период КАК Период, | СведенияОСотрудникахСрезПоследних.Сотрудник КАК Сотрудник, | СведенияОСотрудникахСрезПоследних.Подразделение КАК Подразделение, | СведенияОСотрудникахСрезПоследних.Оклад КАК Оклад | ИЗ | РегистрСведений.СведенияОСотрудниках.СрезПоследних(&ДатаНачала, ) КАК СведенияОСотрудникахСрезПоследних | | ОБЪЕДИНИТЬ ВСЕ | | ВЫБРАТЬ | СведенияОСотрудниках.Период, | СведенияОСотрудниках.Сотрудник, | СведенияОСотрудниках.Подразделение, | СведенияОСотрудниках.Оклад | ИЗ | РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках | ГДЕ | СведенияОСотрудниках.Период МЕЖДУ &ДатаНачала И &ДатаОкончания) КАК ВложенныйЗапрос |; | |//////////////////////////////////////////////////////////////////////////////// |ВЫБРАТЬ | ВложенныйЗапрос.ПериодРегистрации, | ВложенныйЗапрос.Сотрудник КАК Сотрудник, | ВложенныйЗапрос.Подразделение КАК Подразделение, | ВложенныйЗапрос.ВидРасчета, | ВложенныйЗапрос.Оклад, | ВЫБОР | КОГДА ВложенныйЗапрос.Период1 ЕСТЬ NULL | ИЛИ ВложенныйЗапрос.Период1 < ВложенныйЗапрос.ДатаНачала | ТОГДА ВложенныйЗапрос.ДатаНачала | ИНАЧЕ ВложенныйЗапрос.Период1 | КОНЕЦ КАК ПериодДействияНачало, | ВЫБОР | КОГДА ВложенныйЗапрос.Период2 ЕСТЬ NULL | ТОГДА КОНЕЦПЕРИОДА(ВложенныйЗапрос.ДатаОкончания, ДЕНЬ) | ИНАЧЕ ДОБАВИТЬКДАТЕ(ВложенныйЗапрос.Период2, СЕКУНДА, -1) | КОНЕЦ КАК ПериодДействияКонец |ИЗ | (ВЫБРАТЬ | НачислениеЗарплатыОсновныеНачисления.Ссылка.ПериодРегистрации КАК ПериодРегистрации, | НачислениеЗарплатыОсновныеНачисления.Сотрудник КАК Сотрудник, | НачислениеЗарплатыОсновныеНачисления.Подразделение КАК Подразделение, | НачислениеЗарплатыОсновныеНачисления.ВидРасчета КАК ВидРасчета, | втИзмененияОклада1.Оклад КАК Оклад, | НачислениеЗарплатыОсновныеНачисления.ДатаНачала КАК ДатаНачала, | НачислениеЗарплатыОсновныеНачисления.ДатаОкончания КАК ДатаОкончания, | втИзмененияОклада1.Период КАК Период1, | МИНИМУМ(втИзмененияОклада2.Период) КАК Период2 | ИЗ | Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления | ЛЕВОЕ СОЕДИНЕНИЕ втИзмененияОклада КАК втИзмененияОклада1 | ЛЕВОЕ СОЕДИНЕНИЕ втИзмененияОклада КАК втИзмененияОклада2 | ПО втИзмененияОклада1.Сотрудник = втИзмененияОклада2.Сотрудник | И втИзмененияОклада1.Подразделение = втИзмененияОклада2.Подразделение | И втИзмененияОклада1.Период < втИзмененияОклада2.Период | ПО НачислениеЗарплатыОсновныеНачисления.Сотрудник = втИзмененияОклада1.Сотрудник | И НачислениеЗарплатыОсновныеНачисления.Подразделение = втИзмененияОклада1.Подразделение | И (НачислениеЗарплатыОсновныеНачисления.ВидРасчета = ЗНАЧЕНИЕ(ПланВидовРасчета.Основныеначисления.Оклад)) | ГДЕ | НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка | | СГРУППИРОВАТЬ ПО | НачислениеЗарплатыОсновныеНачисления.Ссылка.ПериодРегистрации, | НачислениеЗарплатыОсновныеНачисления.Сотрудник, | НачислениеЗарплатыОсновныеНачисления.Подразделение, | НачислениеЗарплатыОсновныеНачисления.ВидРасчета, | втИзмененияОклада1.Оклад, | НачислениеЗарплатыОсновныеНачисления.ДатаНачала, | НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, | втИзмененияОклада1.Период) КАК ВложенныйЗапрос | |УПОРЯДОЧИТЬ ПО | Сотрудник, | Подразделение, | ПериодДействияНачало»; Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл НоваяЗапись = Движения.ОсновныеНачисления.Добавить(); ЗаполнитьЗначенияСвойств(НоваяЗапись, Выборка); КонецЦикла;

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

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

Запрос = Новый Запрос; Запрос.УстановитьПараметр(«Ссылка», Ссылка); Запрос.Текст = «ВЫБРАТЬ | ВложенныйЗапрос.ПериодРегистрации, | ВложенныйЗапрос.Сотрудник КАК Сотрудник, | ВложенныйЗапрос.Подразделение КАК Подразделение, | ВложенныйЗапрос.ВидРасчета КАК ВидРасчета, | ВложенныйЗапрос.Размер, | ВложенныйЗапрос.ПериодДействияНачало КАК ПериодДействияНачало, | ВложенныйЗапрос.ПериодДействияКонец |ИЗ | (ВЫБРАТЬ | НачислениеЗарплатыОсновныеНачисления.Ссылка.ПериодРегистрации КАК ПериодРегистрации, | НачислениеЗарплатыОсновныеНачисления.Сотрудник КАК Сотрудник, | НачислениеЗарплатыОсновныеНачисления.Подразделение КАК Подразделение, | НачислениеЗарплатыОсновныеНачисления.ВидРасчета КАК ВидРасчета, | НачислениеЗарплатыОсновныеНачисления.Размер КАК Размер, | НачислениеЗарплатыОсновныеНачисления.ДатаНачала КАК ПериодДействияНачало, | ВЫБОР | КОГДА НАЧАЛОПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаНачала, МЕСЯЦ) <> НАЧАЛОПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, МЕСЯЦ) | ТОГДА КОНЕЦПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаНачала, МЕСЯЦ) | ИНАЧЕ КОНЕЦПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, ДЕНЬ) | КОНЕЦ КАК ПериодДействияКонец, | НачислениеЗарплатыОсновныеНачисления.НомерСтроки КАК НомерСтроки | ИЗ | Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления | ГДЕ | НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка | | ОБЪЕДИНИТЬ ВСЕ | | ВЫБРАТЬ | НачислениеЗарплатыОсновныеНачисления.Ссылка.ПериодРегистрации, | НачислениеЗарплатыОсновныеНачисления.Сотрудник, | НачислениеЗарплатыОсновныеНачисления.Подразделение, | НачислениеЗарплатыОсновныеНачисления.ВидРасчета, | НачислениеЗарплатыОсновныеНачисления.Размер, | НАЧАЛОПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, МЕСЯЦ), | КОНЕЦПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, ДЕНЬ), | НачислениеЗарплатыОсновныеНачисления.НомерСтроки | ИЗ | Документ.НачислениеЗарплаты.ОсновныеНачисления КАК НачислениеЗарплатыОсновныеНачисления | ГДЕ | НачислениеЗарплатыОсновныеНачисления.Ссылка = &Ссылка | И НАЧАЛОПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаНачала, МЕСЯЦ) <>
|НАЧАЛОПЕРИОДА(НачислениеЗарплатыОсновныеНачисления.ДатаОкончания, МЕСЯЦ)) КАК ВложенныйЗапрос | |УПОРЯДОЧИТЬ ПО | ВложенныйЗапрос.НомерСтроки, | ПериодДействияНачало»; Пока Выборка.Следующий() Цикл НоваяЗапись = Движения.ОсновныеНачисления.Добавить(); ЗаполнитьЗначенияСвойств(НоваяЗапись, Выборка); КонецЦикла;

18. «Обеспечить пользователю возможность редактировать результат расчета прямо в документе» — такое условие тоже встречается нередко. В этом случае в форме документа размещается кнопка «Расчет», которая и производит весь расчет. Вариант процедуры модуля формы ниже:

ОбъектСервер = РеквизитФормыВЗначение(«Объект»); ОбъектСервер.СформироватьДвиженияДокумента(); Расчет.ПроизвестиРасчетНабора(ОбъектСервер.Движения.ОсновныеНачисления); Расчет.ПроизвестиРасчетНабора(ОбъектСервер.Движения.ДополнительныеНачисления); ОбъектСервер.ОсновныеНачисления.Загрузить(ОбъектСервер.Движения.ОсновныеНачисления.Выгрузить()); ОбъектСервер.ДополнительныеНачисления.Загрузить(ОбъектСервер.Движения.ДополнительныеНачисления.Выгрузить()); ОбъектСервер.Движения.ОсновныеНачисления.Очистить(); ОбъектСервер.Движения.ОсновныеНачисления.Записать(); ОбъектСервер.Движения.ДополнительныеНачисления.Очистить(); ОбъектСервер.Движения.ДополнительныеНачисления.Записать(); ЗначениеВРеквизитФормы(ОбъектСервер,»Объект»);

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

19. Перерасчет только тех записей набора, которые требуют перерасчета. Такое условие есть в нескольких задачах и чтобы его обработать, необходимо процедуру расчета (в моих примерах это ПроизвестиРасчетНабора) модифицировать, чтобы она учитывала переданный второй параметр, НомерСтроки. В случае, если номер строки отличается от Неопределено, процедура должна перерасчитывать только ту запись, номер которой в нее попал. Запрос для связки записей перерасчета с записями регистра, для получения номера строки, ниже:

Запрос = Новый Запрос; Запрос.Текст = «ВЫБРАТЬ | ОсновныеНачисления.НомерСтроки, | «»Основные»» КАК Регистр, | Перерасчет1.ОбъектПерерасчета |ИЗ | РегистрРасчета.ОсновныеНачисления КАК ОсновныеНачисления | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрРасчета.ОсновныеНачисления.Перерасчет1 КАК Перерасчет1 | ПО ОсновныеНачисления.ВидРасчета = Перерасчет1.ВидРасчета | И ОсновныеНачисления.Регистратор = Перерасчет1.ОбъектПерерасчета | И ОсновныеНачисления.Сотрудник = Перерасчет1.Сотрудник | И ОсновныеНачисления.Подразделение = Перерасчет1.Подразделение | |ОБЪЕДИНИТЬ ВСЕ | |ВЫБРАТЬ | ДополнительныеНачисления.НомерСтроки, | «»Дополнительные»», | Перерасчет1.ОбъектПерерасчета |ИЗ | РегистрРасчета.ДополнительныеНачисления КАК ДополнительныеНачисления | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрРасчета.ДополнительныеНачисления.Перерасчет1 КАК Перерасчет1 | ПО ДополнительныеНачисления.ВидРасчета = Перерасчет1.ВидРасчета | И ДополнительныеНачисления.Регистратор = Перерасчет1.ОбъектПерерасчета | И ДополнительныеНачисления.Сотрудник = Перерасчет1.Сотрудник | И ДополнительныеНачисления.Подразделение = Перерасчет1.Подразделение | |ОБЪЕДИНИТЬ ВСЕ | |ВЫБРАТЬ | Удержания.НомерСтроки, | «»Удержания»», | Перерасчет1.ОбъектПерерасчета |ИЗ | РегистрРасчета.Удержания КАК Удержания | ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрРасчета.Удержания.Перерасчет1 КАК Перерасчет1 | ПО Удержания.ВидРасчета = Перерасчет1.ВидРасчета | И Удержания.Регистратор = Перерасчет1.ОбъектПерерасчета | И Удержания.Сотрудник = Перерасчет1.Сотрудник | И Удержания.Подразделение = Перерасчет1.Подразделение»; Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл Если Выборка.Регистр = «Основные» Тогда Набор = РегистрыРасчета.ОсновныеНачисления.СоздатьНаборЗаписей(); ИначеЕсли Выборка.Регистр = «Дополнительные» Тогда Набор = РегистрыРасчета.ДополнительныеНачисления.СоздатьНаборЗаписей(); ИначеЕсли Выборка.Регистр = «Удержания» Тогда Набор = РегистрыРасчета.Удержания.СоздатьНаборЗаписей(); КонецЕсли; Набор.Отбор.Регистратор.Установить(Выборка.ОбъектПерерасчета); Набор.Прочитать(); Набор.Записать(); Расчет.ПроизвестиРасчетНабора(Набор, Выборка.НомерСтроки); КонецЦикла;

20. Заполнение диаграммы Ганта.

// ЗАПРОС ПО ФАКТИЧЕСКОМУ ПЕРИОДУ ДЕЙСТВИЯ Диаграмма.Обновление = Ложь; Диаграмма.Очистить(); Пока Выборка.Следующий() Цикл Серия = Диаграмма.УстановитьСерию(Выборка.Сотрудник); Точка = Диаграмма.УстановитьТочку(Выборка.ВидРасчета); ТекущееЗначение = Диаграмма.ПолучитьЗначение(Точка,Серия); Интервал = ТекущееЗначение.Добавить(); Интервал.Начало = Выборка.ПериодДействияНачало; Интервал.Конец = Выборка.ПериодДействияКонец; КонецЦикла;
Диаграмма.Обновление = Истина;

20. И последнее, но тоже важное. Наиболее оптимальное по соотношению «затраченное время — результат» изменение обработки ЗаполнениеГрафика. В реальной жизни так делать было бы ошибкой, но т.к. вы на экзамене, и перезаполнять данные разных годов, сохраняя предыдущие значения, вам врядли понадобится, имейте ввиду три действия ниже:

Процедура ЗаполнитьГрафик(ДатаНачала, ДатаОкончания, ВыходныеДни, ГрафикРаботы) Экспорт Набор = РегистрыСведений.ГрафикиРаботы.СоздатьНаборЗаписей(); Набор.Отбор.ГрафикРаботы.Установить(ГрафикРаботы); // 1. ДОБАВЛЯЕМ ОТБОР ПО ГРАФИКУ //Набор.Прочитать(); // 2. КОММЕНТИРУЕМ ЧТЕНИЕ НАБОРА ЧислоСекундВСутках = 86400; Дат = ДатаНачала; Для к = 0 По Набор.Количество()-1 Цикл Запись = Набор; Если Запись.Дата < ДатаНачала Тогда Продолжить; ИначеЕсли Запись.Дата =Дат Тогда Если Найти(ВыходныеДни, Строка(ДеньНедели(Дат))) Тогда Запись.Значение = 0; Иначе Запись.Значение = 8; КонецЕсли; Дат = Дат + ЧислоСекундВСутках; Иначе Пока Дат < Мин(Запись.Дата, ДатаОкончания) Цикл НоваяЗапись = Набор.Добавить(); НоваяЗапись.Дата = Дат; Если Найти(ВыходныеДни, Строка(ДеньНедели(Дат))) Тогда НоваяЗапись.Значение = 0; Иначе НоваяЗапись.Значение = 8; КонецЕсли; Дат = Дат + ЧислоСекундВСутках; КонецЦикла; Если Запись.Дата > ДатаОкончания Тогда Прервать; Иначе Если Найти(ВыходныеДни, Строка(ДеньНедели(Дат))) Тогда Запись.Значение = 0; Иначе Запись.Значение = 8; КонецЕсли; КонецЕсли; Дат = Дат + ЧислоСекундВСутках; КонецЕсли; КонецЦикла; Набор.Записать(); Пока Дат <= ДатаОкончания Цикл Запись = Набор.Добавить(); Запись.ГрафикРаботы = ГрафикРаботы; // 3. ВСТАВЛЯЕМ НУЖНЫЙ ГРАФИК Запись.Дата = Дат; Если Найти(ВыходныеДни, Строка(ДеньНедели(Дат))) Тогда Запись.Значение = 0; Иначе Запись.Значение = 8; КонецЕсли; Дат = Дат + ЧислоСекундВСутках; КонецЦикла; Набор.Записать(); КонецПроцедуры

Add a Comment

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