Uploaded by йцу кен

Разработка оперативного учёта в 1С 8.3 [Ильяс Низамутдинов]

advertisement
НИЗАМУТДИНОВ ИЛЬЯС
Разработка
оперативного учета в
1С 8.3
Электронное методическое
пособие
Ижевск, 2019 г
© Июль 2019 г. Низамутдинов Ильяс. Все права защищены
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Оглавление
Введение
4
Глава 1. Основы оперативного учета
6
Глава 2. Реализуем количественный учет
14
Глава 3. Реализуем суммовой учет
68
Глава 4. Блокировка данных при решении задач оперативного учета
115
Глава 5. Работа с последовательностями
146
Заключение
173
3
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Введение
Дорогой коллега! Если Вы читаете эту книгу, то значит, Вы уже освоили
базовые принципы программирования в 1С и хотите двигаться дальше. Как
можно двигаться дальше начинающему разработчику 1С? На мой взгляд,
дальнейшее движение это изучение возможностей 1С по автоматизации
различных видов учета. На сегодняшний момент в 1С 8.3 в глобальном плане
можно автоматизировать три вида учета: оперативный учет, бухгалтерский
учет и учет заработной платы. В этой книге мы изучим основные моменты
автоматизации оперативного учета в 1С 8.3. Главная цель этой книги научить вас понимать, как правильно решать задачи оперативного учета.
Научимся мы это делать на примере простых учебных заданий, которые Вы
сделаете совместно с автором в процессе изучения материалов книги, и
закрепите полученные знания, решая домашние задания.
Как читать эту книгу
Свою книгу я назвал методическим пособием. Что это значит? Для
начала, разберем смысл этих слов – «методическое пособие». Слово
«методичный» означает систематичный, следующий плану, а «пособие» учебная книга. Вместе они означают – учебная книга, в которой дается какойто материал по определенному плану. Это значит, что Вы должны совместно
с книгой шаг за шагом разбирать те примеры, которые в ней даются, причем
в том порядке, в каком они идут в книге. Так Вы максимально эффективно
погрузитесь в изучаемую тему. Очень желательно, чтобы Вы эти примеры
реализовывали самостоятельно в собственной конфигурации. Причем нужно
не просто их копировать, а выполнять по памяти то, что Вы прочитали. После
каждой главы есть домашние задания для самостоятельной работы.
Рекомендую все их решить, прежде чем приступать к изучению следующей
главы.
Структура книги
В первой главе мы узнаем, что такое оперативный учет, его основные
цели, задачи и области применения. Узнаем, при помощи каких объектов
метаданных в платформе 1С 8.3 реализуются задачи оперативного учета.
4
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Во второй главе мы реализуем самый простой вид оперативного учета –
количественный, с нуля разработаем конфигурацию, в которой будет
реализована простая задача автоматизации количественного оперативного
учета. Сначала мы разберем самый примитивный вариант – без учёта
складов, а потом усложним задачу, разработав многоскладской
количественный учет.
В третьей главе мы погрузимся в суммовой учет. Разберем основные
способы ведения суммового учета, узнаем, что такое партионный учет,
внедрим учёт цен в нашу конфигурацию, реализуем регистрацию продаж, а
также разработаем отчет «Валовая прибыль и себестоимость».
Материал четвертой главы Вас познакомит с транзакциями и
блокировками данных: Вы узнаете, какие виды транзакций бывают и
особенности их применения, познакомитесь с видами блокировок и
научитесь их применять в задачах оперативного учета.
И в пятой главе Вы научитесь работать с последовательностями, мы
внедрим механизм последовательностей в уже реализованные примеры с
количественным и суммовым учётом.
После изучения примеров пособия, решения домашних заданий Вы
сами почувствуете, что Ваше программирование в 1С вышло на новый
уровень.
И я открою Вам небольшой секрет: изложенных примеров вполне
достаточно, чтобы начать готовится к экзамену «1С: Специалист по
платформе «1С:Предприятие 8» (задачи по оперативному учёту).
5
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Глава 1. Основы оперативного учета
Прежде чем начать изучать оперативный учет на практике и
разрабатывать конфигурации, в которых будут реализованы те или иные
задачи оперативного учета, узнаем, какие виды учета существуют и в чем
особенность оперативного учета, а также в каких случаях он может
применяться.
На текущий момент в Российской Федерации распространены четыре
направления хозяйственного учета в организациях: бухгалтерский,
налоговый, статистический и оперативный. Дадим краткие определения
каждому из этих направлений учета.
Бухгалтерский учет – осуществляет наблюдение и контроль над всеми
объектами хозяйственной деятельности предприятия, а также над
операциями, которые совершаются с этими объектами.
Налоговый учет – осуществляет наблюдение за доходами и расходами
организации, для последующего формирования налогооблагаемой базы.
Статистический учет – фиксирует финансовые и экономические показатели
состояния предприятия при помощи специальных методов статистики.
Данная информация используется органами власти и управления для
последующего анализа.
Оперативный учет – осуществляет наблюдение над текущим состоянием
отдельных объектов хозяйственной деятельности предприятия.
С налоговым и статистическим учетом все понятно – с их помощью
собирается информация необходимая для органов государственной власти
(федеральная налоговая служба и федеральная служба государственной
статистики).
Бухгалтерский учет необходим для сбора информации о всей
хозяйственной деятельности предприятия. Причем, эта информация может
быть предоставлена как на текущий момент, так и за прошедший период, т.е.
спустя некоторое время после совершения той или иной операции над
объектом хозяйственной деятельности.
6
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Оперативный же учет ведется только над некоторыми объектами
хозяйственной деятельности (например, товарооборот или выпуск
продукции) и необходим для текущего управления.
Итак, выделим два основных признака, которые кардинально отличают
оперативный учет от бухгалтерского:
Первый признак. Избирательность объектов учета: если бухгалтерский учет
осуществляет сбор и анализ информации по всем объектам хозяйственной
деятельности, то оперативный учет только по некоторым.
Второй признак. Получение текущей информации об объекте учета. Над
объектами оперативного учета операции осуществляются очень часто в
течение времени. И поэтому для эффективного управления нужно обладать
информацией о текущем состоянии этих объектов.
Возьмем, к примеру, такие объекты бухгалтерского учета как основные
средства и товары. Операции над основными средствами осуществляются
крайне редко (раз в год или даже раз в несколько лет), в тоже время
операции над товарами (особенно в розничной торговле) могут
осуществляться ежедневно (ежечасно, ежеминутно). Поэтому в некоторых
случаях для качественного управления предприятием необходимо вести
оперативный учет движения товаров.
Разберем цели, задачи, основные методы оперативного учета. А также
узнаем, в каких областях можно применять оперативный учет.
Цели и задачи.
В теории целей оперативного учета достаточно много, но мы
рассмотрим самую основную, ту, ради которой организуется оперативный
учет в системе программных продуктов «1С: Предприятие».
Целью оперативного учета является мгновенный и ежедневный
(ежечасный) сбор информации о текущем состоянии некоторых
хозяйственных процессов предприятия.
Оперативный учет позволяет нам в текущий момент времени мгновенно
получить информацию о состоянии нужного объекта учета. Например, это
7
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
могут быть остатки товаров на складах, выпуск продукции или информация о
наличии денежных средств в кассе предприятия.
Рассмотрим основные задачи, которые могут возникнуть в процессе
хозяйственной деятельности предприятия. Для решения этих задач
необходимо применять методы оперативного учета.






Анализ товарных запасов на складах предприятия и контроль
материальных ценностей на производстве (сырье, расходные
материалы и т.д.);
Контроль наличия денежных средств в кассе (на расчетном счету)
предприятия;
Информация о поступлении денежных средств за оказанные услуги или
реализованную продукцию;
Оперативный контроль над выпуском продукции;
Резервирование товара на складе для определенного покупателя;
Организация работы с заказами поставщиков и покупателей.
Таким образом, все задачи, возникающие в процессе хозяйственной
деятельности предприятия, где требуется оперативная (текущая и
мгновенная) информация о нужном объекте хозяйственной деятельности
решаются при помощи оперативного учета.
Методы оперативного учета
Суть любого метода оперативного учета в непосредственном
наблюдении за хозяйственной операцией, которое необходимо для
адекватного отображения ситуации происходящей на предприятии. Причем
хозяйственная операция может быть та, которая не отображается в
бухгалтерском учете (например, резервирование товаров).
Рассмотрим основные методы оперативного учета, которые Вам могут
встретиться при работе с программными продуктами в системе «1С:
Предприятие».



Контроль остатков товаров на складах предприятия;
Наблюдение за денежными средствами организации;
Анализ заказов на производство для адекватной
производственных мощностей;
8
загрузки
Низамутдинов Ильяс


Разработка оперативного учёта в 1С 8.3
Анализ заказов покупателя с целью правильного и своевременного
формирования заказов поставщику;
Контроль над резервами товарной продукции на складе.
В методах оперативного учета производится оценка некоторых
переменных. Это могут быть натуральные или денежные измерители. То
есть, оперативный учет можно осуществлять в натуральных или
количественных измерителях – анализируется количество товаров на складе
(в производстве, в резерве и т.д.) в штуках, килограммах, тоннах и т.п.; а
также в денежных или суммовых измерителях, т.е. анализируется стоимость
этих товаров (например, для оценки валовой прибыли от продажи товаров).
Области применения
Рассмотрим, в каких областях хозяйственной деятельности имеет смысл
организовывать оперативный учет. Список ниже является открытым, и я его
сформировал согласно своему практическому опыту. В реальной жизни
ситуаций, когда необходимо внедрять оперативный учет может быть
больше.

Автоматизация розничной торговли.
В розничной торговле необходимо обладать оперативной информацией
о товарных остатках в магазине (на складе). Также при автоматизации
розничной торговли очень часто необходим функционал формирования
заказов поставщикам и покупателям.

Автоматизация оптовой торговли.
При осуществлении оптовой торговли оперативный учет можно
применять в следующих случаях: контроль остатков на складах,
резервирование товарной продукции для конкретного покупателя,
работа с заказами поставщиков и покупателей.

Автоматизация производственного процесса.
При производственном процессе необходимо контролировать наличие
материалов на складе и в производстве, загрузку оборудования;
получать оперативную информацию о выпуске продукции; осуществлять
9
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
мониторинг выполнения заказов покупателей, поставщиков и заказов на
производство.
Реализация оперативного учета в 1С 8.3
Оперативный учет в системе «1С: Предприятие 8.3» реализуется
посредством документов и регистров накопления. Для отражения факта
какого-либо события с объектом учета (например, поступления товара на
склад) документ должен осуществить запись в регистр накопления.
Впоследствии, при помощи отчетов, которые работают с регистрами
накопления, можно получить оперативную информацию о состоянии того
или иного объекта учета (например, текущий остаток товара на складе).
Для осуществления записи документа в регистр существует механизм
проведения документа.
Для отражения событий оперативного учета
платформа 1С 8 позволяет разделить случаи, когда документ отражает
событие реального времени, а когда документ отражает уже свершившийся
ранее факт.
Поэтому документы в «1С: Предприятие 8» могут проводиться в
оперативном режиме, т.е. регистрировать события, которые свершаются в
настоящем времени, и в неоперативном режиме, то есть регистрировать
свершившийся факт, который нужно зафиксировать в программе. Для того,
чтобы документ имел возможность проводиться в оперативном режиме,
необходимо в свойство документа «Оперативное проведение» установить
значение «Разрешить».
Рис. 1.1.
10
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
После этого у документа появятся следующие особенности:
1)
2)
3)
Документ нельзя провести будущим числом;
При проведении текущим числом, время документа будет установлено
на текущее время;
Если документ проводится текущей датой и текущим временем, то он
проводится в оперативном режиме, если проводится за прошлое число
– в неоперативном режиме.
Во время проведения можно определить, в каком режиме проводится
документ. Реализуется это при помощи значения второго параметра
обработчика ОбработкаПроведения, который расположен в модуле
документа.
Рис. 1.2.
Если документ проводится в оперативном режиме, то этот параметр
принимает значение Оперативный системного перечисления
РежимПроведенияДокумента, а иначе – Неоперативный.
Рис. 1.3.
Фирма 1С рекомендует при оперативном проведении осуществлять
различные проверки правомерности проведения документов (контроль
остатков и т.д.), поскольку при оперативном проведении будут использованы
11
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
текущие остатки, которые всегда поддерживаются в актуальном состоянии. А
при неоперативном проведении остатки будут вычисляться, что
отрицательно скажется на производительности системы в целом. Кроме
того, нет смысла при неоперативном проведении проводить различные
проверки, поскольку неоперативное проведение - это уже свершившийся
факт, который необходимо отразить в учете. А если, и возникнет какая-либо
ошибка связанная с нехваткой того или иного остатка, то это уже будет
ошибка не этого документа, а ошибка, которая была совершена когда-то
ранее в других документах.
Прежде чем приступить к решению некоторых задач хозяйственной
деятельности, где применим оперативный учет, резюмируем знания,
полученные в этой главе. Под оперативным учетом понимается мгновенное
получение текущей информации о состоянии некоторых объектов
хозяйственной деятельности предприятия. Целью оперативного учета
является ежедневный сбор информации о текущем состоянии хозяйственных
процессов, над которыми этот учет осуществляется. В основном задачами
оперативного учета являются задачи контроля материальных ценностей и
задачи организации эффективного управления.
Оперативный учет необходимо внедрять в тех областях хозяйственной
деятельности, где необходим текущий контроль над различными
процессами и есть потребность в мгновенном получении информации о
состоянии того или иного объекта учета.
Для осуществления оперативного учета в системе программ «1С:
Предприятие 8» имеется возможность проводить документы в оперативном
и неоперативном режиме. Оперативный режим предполагает, что событие
осуществляется в текущий момент времени, при этом целесообразно
проводить различные проверки правомерности осуществления операции.
При неоперативном режиме отображается факт наступления уже
произошедшего события, при этом не целесообразно осуществлять
различные проверки корректности данных.
12
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Во второй главе мы разберем простую складскую задачу, где реализуем
количественный учет, а в третьей главе реализуем задачу, в которой будем
вести суммовой учет товаров, а также рассчитывать их себестоимость.
13
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Глава 2. Реализуем количественный учет
Постановка задачи
Нам нужно реализовать учет товаров в магазине: в магазин поступают
товары (без разницы от кого), потом эти товары отгружаются покупателям
(без разницы кому). Необходимо организовать контроль остатков товаров –
покупателю можно отгрузить только то количество товара, которое имеется в
данный момент в организации. Если нужного товара нет в магазине (или не
хватает количества), отгрузка этого товара будет не возможна. В любой
момент пользователь может получить текущие остатки товаров в магазине.
Разработка конфигурации
Создадим новую пустую конфигурацию (см. рис 2.1 - 2.5).
Рис. 2.1.
Рис. 2.2.
14
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.3.
Рис. 2.4.
Рис. 2.5.
15
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
После того, как будет создана конфигурация, откройте конфигуратор и
зайдите в свойства конфигурации (см. рис. 2.6).
Рис. 2.6.
В правой части рабочего стола откроется панель свойств. Введем в
свойство «Имя» - «КоличественныйОперативныйУчет», свойство «Синоним»
поменяется автоматически (см. рис 2.7). Остальные свойства трогать не
будем, и все оставим как есть.
Рис. 2.7.
Теперь подумаем, какие объекты метаданных нам нужно добавить.
Начнем со справочников. Перечитав постановку задачи ещё раз, мы
16
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
понимаем, что у нас, очевидно, один магазин, нет конкретных поставщиков и
покупателей (аналитика по ним не важна), но могут быть различные товары.
Поэтому имеет смысл создать пока только один справочник, который
назовем «Номенклатура» (см. рис. 2.8).
Рис. 2.8.
Перейдем к документам. По условию задачи необходимо
регистрировать приход товаров и расход товаров (или продажу). Делать мы
это будем при помощи документов «Приход» и «Расход». У этих документов
будет табличная часть «Список товаров» с реквизитами «Номенклатура» (тип
СправочникСсылка.Номенклатура) и «Количество» (тип число (10,2)).
Создадим документ «Приход» (см. рис. 2.9) и табличную часть документа с
реквизитами (см. рис. 2.10).
Рис. 2.9.
17
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.10.
Обратите внимание на закладку «Движения» - в свойствах
«Проведение» и «Оперативное проведение» должны быть установлены
значения «Разрешить» (см. рис. 2.11).
Рис. 2.11.
Теперь, чтобы не делать лишнюю работу скопируем вновь созданный
документ: выделим его в окне метаданных, нажмем Ctrl+C, а потом Ctrl+ V.
Будет создан документ «Приход1» (см. рис 2.12), который переименуем в
«Расход» (см. рис. 2.13).
Рис. 2.12.
18
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.13.
Чтобы было удобнее работать, создадим журнал документов
ПриходРасход, где укажем в качестве регистрирующих документов оба
созданных документа.
Рис. 2.14.
Документы мы создали, теперь нужно создать регистр накопления.
Сконструируем этот регистр, но сначала определим, какого вида должен
быть этот регистр накопления (остатки или обороты). Для этого обратим
внимание на эту строку постановки задачи: «Необходимо организовать
контроль остатков товаров…», т.е. нам нужно будет знать, какое количество
какого товара находится в магазине.
Напомню, чем отличается регистр накопления с видом «Остатки» от
регистра накопления с видом «Обороты». В первом случае фиксируется
приход и расход. Т.е. какой-то документ делает движения со знаком плюс
(увеличивает количество чего-либо), а какой-то со знаком минус (уменьшает
количество чего-либо), также можно видеть остатки по этому товару (приход
минус расход). В тоже время оборотный регистр фиксирует только сам факт
движения (например, факт продажи товара).
19
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Регистры накопления состоят из измерений, ресурсов и реквизитов.
Ресурс всегда имеет числовой тип и в нем хранятся, накапливаемые
значения. Именно значения ресурсов будут увеличиваться при приходе, и
уменьшаться при расходе. В измерениях хранится та аналитика, в разрезе
которой учитывается наш ресурс. Если мы увеличиваем (уменьшаем)
количество какого-нибудь товара, то у нас должно быть измерение Товар, в
котором будет храниться ссылка на соответствующий товар. Если же у нас по
условиям задачи необходимо вести аналитику в нескольких разрезах
(например, есть еще склады), то нам необходимо добавлять
соответствующие измерения.
Ниже мы усложним нашу задачу, добавив измерение – Склады (см. стр.
43)!
Исходя из только что полученных знаний и условий задачи, мы
понимаем, что наш регистр, назовем его «Остатки товаров», должен быть с
видом «Остатки» (см. рис. 2.15). Он должен иметь одно измерение
«Товары» (тип ссылка на справочник «Номенклатура»), и один ресурс –
«Количество» (тип Число(10,2)), см. рис. 2.16.
Рис. 2.15.
20
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.16.
Добавим оба документа в регистраторы этого регистра (см. рис. 2.17).
Рис. 2.17.
Конфигурацию мы сконструировали, теперь переходим к реализации
нашей задачи. Первым делом, реализуем приход по регистру накопления
при помощи документа «Приход». Для удобства и быстроты я воспользуюсь
конструктором движений: выделим документ «Приход» в дереве
конфигурации, вызовем контекстное меню, в котором нас интересует
команда «Конструктор движений» (см. рис. 2.18).
21
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.18.
Выполним эту команду, и откроется конструктор движения регистров
(см. рис. 2.19).
Рис. 2.19.
Тип движения регистра оставим «Приход», а также выберем табличную
часть «Список товаров» (см. рис. 2.20).
Рис. 2.20.
22
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Заполним поля в таблице внизу конструктора. Измерение «Товар»
свяжем с реквизитом «Номенклатура» табличной части, а ресурс
«Количество» с реквизитом «Количество» (см. рис. 2.21).
Рис. 2.21.
Нажмем кнопку «Ок» конструктора, и в модуле документа «Приход»
появится следующий код (см. листинг 2.1).
Процедура ОбработкаПроведения(Отказ, Режим)
//{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения
будут утеряны!!!
// регистр ОстаткиТоваров Приход
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаСписокТоваров Из СписокТоваров Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
КонецЦикла;
//}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
КонецПроцедуры
Листинга 2.1.
С этим кодом все понятно: мы обходим циклом табличную часть
«Список товаров» документа «Приход», и в каждой итерации цикла
добавляем запись в регистр накопления «Остатки товаров», причем в
свойство Вид движения записываем значение «Приход» системного
перечисления ВидДвиженияНакопления.
Нам осталось реализовать проведение документа «Расход» по регистру
«Остатки товаров», причем мы должны контролировать остаток, и если
нужного количества товара нет в магазине, то запрещать проводить
23
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
документ. Имеется два способа осуществления контроля остатков – по
«старой методике», когда сначала проверяется остаток на складе, а потом
документ делает движение, и по «новой методике», когда сначала делается
движение по регистру, а потом уже с учетом сделанных движений
проверяется остаток на складе.
Именно контроль остатков по «новой» методике должен применяться
при сдаче экзамена «1С: Специалист по технологической платформе».
В этой книге контроль остатков мы будем осуществлять по «новой»
методике: сначала спишем товар - сделаем движения в регистре, а потом
проверим остаток. Если по итогу списания остаток по какому-нибудь товару
уйдет в минус, то сообщим об этом оператору и отменим проведение
документа.
Для реализации движений документа «Расход» я не буду использовать
конструктор движений как это было сделано ранее, поэтому создадим
процедуру «ОбработкаПроведения» в модуле документа «Расход» (см. рис.
2.22 и 2.23).
Рис. 2.22.
24
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.23.
Рис. 2.24.
Первым делом, как уже было сказано, мы реализуем проведение по
регистру «ОстаткиТоваров». Для этого мы создадим запрос, в котором
получим данные табличной части нашего документа сгруппированные по
номенклатуре (поскольку пользователи могут вводить строки с одинаковым
товаром), результат запроса мы поместим во временную таблицу ДокТЧ
(потом она нам пригодится), после чего получим выборку этой временной
таблицы. А теперь разберем все вышеперечисленное более подробно:
Создаем объект запрос в новой процедуре обработки проведения:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст = "";
КонецПроцедуры
Листинг 2.2.
Вызываем конструктор запроса, в котором выбираем таблицу
СписокТоваров документа «Расход», у этой таблицы выберем поля
Номенклатура и Количество (см. рис. 2.25).
25
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.25.
В закладке «Группировка» выберем в качестве группового поля поле
Номенклатура, а в качестве суммируемого поля – поле Количество
(функция Сумма).
Рис. 2.26.
На закладке «Условия» сделаем отбор по нашему документу (поле
ссылка).
Рис. 2.27.
На закладке «Дополнительно» создадим временную таблицу, которую
назовем ДокТЧ.
26
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.28.
На закладке «Индекс» проиндексируем временную таблицу по полю
Номенклатура.
Рис. 2.29.
На
закладке
«Объединение/псевдонимы»
Номенклатура псевдоним «Товар».
присвоим
полю
Рис. 2.30.
Мы создали временную таблицу, которую потом будем также
использовать при контроле остатков, но нам нужно её обойти для записи
данных в регистр, поэтому создадим выборку по этой таблице. Для этого
перейдем в «Пакет запросов» и создадим новый запрос.
Рис. 2.31.
В новом запросе выберем временную таблицу ДокТЧ и все её поля.
27
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.32.
Создадим запрос, получится следующий код:
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|
РасходСписокТоваров.Номенклатура КАК Товар,
|
СУММА(РасходСписокТоваров.Количество) КАК Количество
|ПОМЕСТИТЬ ДокТЧ
|ИЗ
|
Документ.Расход.СписокТоваров КАК РасходСписокТоваров
|ГДЕ
|
РасходСписокТоваров.Ссылка = &Ссылка
|
|СГРУППИРОВАТЬ ПО
|
РасходСписокТоваров.Номенклатура
|
|ИНДЕКСИРОВАТЬ ПО
|
Товар
|;
|
|////////////////////////////////////////////////////////////////////////////
////
|ВЫБРАТЬ
|
ДокТЧ.Товар КАК Товар,
|
ДокТЧ.Количество КАК Количество
|ИЗ
|
ДокТЧ КАК ДокТЧ";
Листинг 2.3.
Создадим менеджер временных таблиц (для того, чтобы потом мы
могли использовать временную таблицу ДокТЧ в другом запросе),
передадим в качестве параметра ссылку на документ, а потом получим
выборку по запросу.
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.УстановитьПараметр("Ссылка",Ссылка);
Результат = Запрос.Выполнить();
Выборка
= Результат.Выбрать();
Листинг 2.4.
28
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Обойдем полученную выборку и запишем данные в регистр накопления
«Остатки товаров».
Движения.ОстаткиТоваров.Записывать = Истина;
Пока Выборка.Следующий() Цикл
НовоеДвижение = Движения.ОстаткиТоваров.Добавить();
ЗаполнитьЗначенияСвойств(НовоеДвижение,Выборка);
НовоеДвижение.ВидДвижения = ВидДвиженияНакопления.Расход;
НовоеДвижение.Период = Дата;
КонецЦикла;
Движения.ОстаткиТоваров.Записать();
Листинг 2.5.
Данные в регистр мы записали, теперь проверим остатки номенклатуры.
Если остаток по какой-либо номенклатуре стал меньше нуля, то отменим
проведение документа и выведем соответствующее сообщение
пользователю.
В текущем объекте Запрос мы создадим новый запрос, в котором будем
использовать уже созданную ранее временную таблицу ДокТЧ.
Это
возможно
потому,
что
мы
свойству
объекта
Запрос
МенеджерВременныхТаблиц присвоили вновь созданный менеджер
временных таблиц (см. листинг 2.4), в котором и хранятся временные
таблицы запроса.
У нашего объекта Запрос обратимся к свойству Текст, присвоим ему
пустую строку, и вызовем конструктор запроса, в котором создадим
описание временной таблицы.
Рис. 2.33.
29
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Имя временной таблицы будет ДокТЧ, оно обязательно должно
совпадать с именем временной таблицы, которую мы создали ранее. И
создадим одно поле Товар. Имя этого поля также должно совпадать с
именем поля в ранее созданной временной таблице.
Рис. 2.34.
Создадим эту таблицу, а также выберем виртуальную таблицу Остатки
регистра накопления «Остатки товаров».
Рис. 2.35.
Перейдем на закладку «Связи» и свяжем левым соединением
временную таблицу ДокТЧ с виртуальной таблицей Остатки регистра
накопления «Остатки товаров» по полю «Товар».
Рис. 2.36.
30
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Перейдем обратно в закладку «Таблицы и поля», выделим виртуальную
таблицу «Остатки» регистра накопления и вызовем параметры этой
виртуальной таблицы.
Рис. 2.37.
В свойство Период запишем параметр &МометВремени.
Рис. 2.38.
В свойстве Условия сделаем отбор только по тем товарам, которые
имеются во временной таблице ДокТЧ.
31
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.39.
Параметры виртуальной таблицы мы задали, теперь выберем поля
Товар временной таблицы и поле КоличествоОстаток виртуальной
таблицы. Информация из этих полей будет выводиться пользователю в
сообщениях.
Рис. 2.40.
Применим функцию Представление к полю Товар.
Рис. 2.41.
32
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
А к полю КоличествоОстаток применим функцию ЕстьNULL (может
возникнуть ситуация, когда номенклатуры из табличной части не будет в
регистре накопления, в том случае, когда мы все списали) со знаком минус.
Рис. 2.42.
Зададим псевдонимы для полей.
Рис. 2.43.
Сохраним запрос и передадим в него параметр момент времени.
//контроль остатков
Запрос.Текст = "ВЫБРАТЬ
|
ПРЕДСТАВЛЕНИЕ(ДокТЧ.Товар) КАК Товар,
|
- ЕСТЬNULL(ОстаткиТоваровОстатки.КоличествоОстаток, 0)
КАК Остаток
|ИЗ
|
ДокТЧ КАК ДокТЧ
|
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрНакопления.ОстаткиТоваров.Остатки(
|
&МоментВремени,
|
Товар В
|
(ВЫБРАТЬ
|
вт.Товар
|
ИЗ
|
ДокТЧ КАК вт)) КАК
ОстаткиТоваровОстатки
|
ПО ДокТЧ.Товар = ОстаткиТоваровОстатки.Товар";
Запрос.УстановитьПараметр("МоментВремени",
33
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
?(РежимПроведения =
РежимПроведенияДокумента.Оперативный,
Новый
Граница(МоментВремени(),ВидГраницы.Включая),
Неопределено));
Листинг 2.6.
При установке параметра, мы определяем, в каком режиме (см. глава 1,
стр. 11), проводится наш документ. Если документ проводится в
оперативном режиме, то получаем остатки на границу документа (Объект
Граница мы разберем в следующей подглаве ниже (см. стр. 43)). Если
документ проводится в неоперативном режиме, то получим текущие остатки
(если в таблицу остатков в значение периода передан параметр
Неопределено, то таблица возвращает актуальный остаток), чтобы узнать,
как проведение документа «задним числом» изменило ситуацию в целом.
Получим выборку из запроса, обойдем её, и если где-то поле остаток
больше 0 (при некорректном проведении остатки должны стать
отрицательные, но мы в запросе перед полем остаток установили знак «-»,
поэтому запрос возвращает положительные данные), то выведем сообщение
оператору. А при оперативном проведении откажемся проводить документ.
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.Остаток > 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Товара " + Выборка.Товар + " не хватает " +
Выборка.Остаток;
Сообщение.Сообщить();
Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Листинг 2.7.
На этом, проведение документа «Расход» реализовано.
Сохраним конфигурацию, обновим базу данных, зайдем в справочник
«Номенклатура» и создадим несколько позиций.
34
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.44.
Создадим и проведем три документа прихода со следующими
наборами товаров:
Приход 1:
Молоко – 1 шт.
Хлеб – 3 шт.
Приход 2:
Хлеб – 3 шт.
Сметана – 1 шт.
Приход 3:
Хлеб – 1 шт.
Теперь создадим и проведем документ «Расход»
Сметана – 2 шт.
Хлеб – 3 шт.
Документ не будет проведен и выйдет сообщение, что не хватает 1 штуки
сметаны.
35
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.45.
Это и правильно, поскольку был приход только на 1 штуку сметаны, а
мы пытаемся списать 2 штуки – одной не хватает. Теперь исправим
количество сметаны на 1 штуку и проведем документ.
Рис. 2.46.
В этом случае документ будет проведен.
Создадим новый документ «Расход»:
Яблоки – 2 шт.
Хлеб – 10 шт.
Молоко – 2 шт.
И попробуем его провести.
36
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.47.
Выведено сообщение о том, что молока не хватает 1 штуки (всего в
магазине было 1 штука, а пытаемся списать две), хлеба не хватает шесть штук
(всего было 7 штук, списали предыдущим документом 3 штуки, осталось 4
штуки, пытаемся списать 10 штук), а яблок вообще нет в магазине.
Задача реализована!
Момент времени и граница
В листинге 2.6 (стр. 34) я передал в запрос не дату документа, а объект
Граница в котором использовал метод объекта документ МоментВремени(). Для многих может быть не совсем понятен смысл этого
объекта и метода, поэтому сейчас мы более подробно с ними познакомимся.
Момент времени
Очень часто в базе может быть несколько документов одного типа с
одинаковой датой и временем (вплоть до секунды), но все эти документы не
могли быть созданы одномоментно. Даже если они были созданы в одну
37
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
секунду, то какой-то был создан чуть-чуть раньше, а какой-то чуть-чуть
позже. Но если мы эти документы будет сравнивать по дате документа, то
получится, что они все созданы в одно время, что не соответствует
действительности. Возникает определенная проблема: как учесть, что один
документ был создан раньше другого, хотя у них одинаковая дата и время
вплоть до секунды. Чтобы разрешить эту проблему, в 1С 8 имеется
универсальный объект МоментВремени.
При помощи объекта
МоментВремени можно однозначно распределить на временной оси
документы с одинаковой датой и одинаковым временем (одного типа). Для
этого у данного объекта имеется два свойства – дата (тип ДатаВремя) и
ссылка на документ.
Например, у нас созданы документы «Расход» с одной датой и одним
временем в следующем порядке.
Документ
Порядок создания
Расход №1 от 01.04.2019 13:00:00
Первый
Расход №2 от 01.04.2019 13:00:00
Второй
Табл. 2.1
Тогда на временной оси моменты времени этих документов будут
расположены следующим образом (см. рис. 2.48).
Рис. 2.48.
38
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Где МоментВремени1 – это момент времени документа Расход №1 от
01.04.2019 13:00:00, а МоментВремени2 - момент времени документа Расход
№2 от 01.04.2019 13:00:00
Разберемся, как получить момент времени документа. Сделать это
можно двумя способами. Первый способ – используя метод
МоментВремени(). Этот метод имеется у ссылки документа и объекта
документа (см. листинг 2.8). Второй способ – используя конструктор Новый,
где в качестве первого параметра указать дату, а в качестве второго
параметра ссылку на документ (листинг 2.9).
МоментВремени = СсылкаДок.МоментВремени();
Листинг 2.8.
МоментВремени = Новый МоментВремени(СсылкаДок.Дата, СсылкаДок);
Листинг 2.9.
Где СсылкаДок – ссылка на конкретный документ.
Моменты времени можно сравнивать между собой. Для этого
используется метод объекта Сравнить. Данный метод работает следующим
образом (применительно к моментам времени с рисунка 2.47):
РезультатСравнения = МоментВремени1.Сравнить(МоментВремени2);
Листинг 2.10.
Где РезультатСравнения равняется или -1, если МоментВремени2
позже по времени чем МоментВремени1 (это показано на рисунке 2.47), или
1, если МоментВремени1 позже по временной оси чем МоментВремени2.
Задание для самостоятельных: сделайте обработку, которая будет
сравнивать моменты времени двух документов (ссылки на документы
вводятся в форме обработки).
Мы узнали, что такое момент времени и как его получать. Теперь
познакомимся с тем, как можно использовать момент времени при расчете
остатков. Для этого расширим пример с таблицы 2.1, введя документ Приход,
а также добавив колонку количество товара, который был оприходован или
списан соответствующими документами.
39
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Документ
Порядок создания
Количество товара
(товар «Хлеб»)
Приход №4 от 01.04.2019
12:59:59
Первый
7
Расход №3 от 01.04.2019
13:00:00
Второй
3
Расход №4 от 01.04.2019
13:00:00
Третий
2
Табл. 2.2
Теперь узнаем, как у нас будут считаться остатки, если мы в запрос
передадим момент времени в качестве периода виртуальной таблицы
Остатки регистра накопления. Для наглядности, я сделаю простую
обработку. На форме этой обработки будут следующие реквизиты:
Документ1 и Документ2 (тип ссылка на документ «Приход»), Остаток 1 и
Остаток2 (тип число), Товар (тип ссылка на справочник «Товары»). Все эти
реквизиты разместим на форме, а также создадим команду «Получить
остаток», которую также разместим на форме (см. рис. 2.48).
Рис. 2.49.
40
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
В базе я создал набор документов аналогичный набору из таблицы 2.2, с
единственным товаром «Хлеб», количество этого товара, соответствует
количеству из таблицы. Все документы проведены.
Рис. 2.50.
Теперь, сделаем обработчик команды «Получить остаток», где в запросе
при помощи виртуальной таблицы Остатки регистра накопления «Остатки
товаров» будем получать остатки конкретного товара. В период виртуальной
таблицы передадим момент времени документа. Поскольку нам нужно
получить остатки для двух разных моментов времени, то мы будем
использовать пакет запроса, где в первом запросе передаем в параметр
Период момент времени первого документа, а во втором запросе – момент
времени второго документа. После обработаем результат запроса и выведем
полученные остатки в нужный реквизит.
&НаСервере
Процедура ПолучитьОстатокНаСервере()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|
ОстаткиТоваровОстатки.КоличествоОстаток КАК Остаток
|ИЗ
|
РегистрНакопления.ОстаткиТоваров.Остатки(&МоментВремени1, Товар = &Товар) КАК
ОстаткиТоваровОстатки
|;
|
|////////////////////////////////////////////////////////////////////////////
////
|ВЫБРАТЬ
|
ОстаткиТоваровОстатки.КоличествоОстаток КАК Остаток
|ИЗ
|
РегистрНакопления.ОстаткиТоваров.Остатки(&МоментВремени2, Товар = &Товар) КАК
ОстаткиТоваровОстатки";
41
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Запрос.УстановитьПараметр("Товар",Товар);
Запрос.УстановитьПараметр("МоментВремени1",Новый
МоментВремени(Документ1.Дата,Документ1));
Запрос.УстановитьПараметр("МоментВремени2",Новый
МоментВремени(Документ2.Дата,Документ2));
МассивРезультатов = Запрос.ВыполнитьПакет();
Выборка1 = МассивРезультатов[0].Выбрать();
Выборка2 = МассивРезультатов[1].Выбрать();
Выборка1.Следующий();
Выборка2.Следующий();
Остаток1 = Выборка1.Остаток;
Остаток2 = Выборка2.Остаток;
КонецПроцедуры
&НаКлиенте
Процедура ПолучитьОстаток(Команда)
ПолучитьОстатокНаСервере();
КонецПроцедуры
Листинг 2.11.
Посмотрим, какой результат будет у нашей обработки.
Рис. 2.51.
В первом случае (остаток на момент времени документа один) мы
получили остаток равный количеству товара в приходе. А во втором случае –
остаток равный количеству товара в приходе минус количество товара в
первом расходе.
Таким образом. Получая остаток на момент времени документа, мы
получаем остаток товара до движения этого документа по регистрам.
Момент времени документа начинается до того, как этот документ сделает
движения. Наглядно это демонстрируется на рисунке 2.52.
42
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.52.
Из всего вышесказанного делаем вывод: если нам нужно узнать остатки,
которые были перед проведением документа, которые не включают
движения этого документа, то для контроля остатков можно использовать
объект момент времени. Если же нам нужно узнать остатки, в которые уже
включены движения исследуемого документа, то этот объект использовать
нельзя.
Чтобы узнать остатки вместе с движением документа, необходимо
использовать объект Граница.
Граница
Граница это универсальный объект, который указывает, что в
применяемом интервале используются (или не используются) граничные
значения. В нашем случае, мы можем указать, что момент времени какоголибо документа берется вместе с движениями этого документа (его
граничным значением).
Объект Граница создается при помощи конструктора Новый, который
имеет следующий синтаксис:
Новый Граница(<ЗначениеГраницы>,<ВидГраницы>)
43
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Где:
ЗначениеГраницы – произвольное значение, которое содержит значение
границы (в нашем случае МоментВремени).
ВидГраницы – системное перечисление ВидГраницы, которое имеет два
значения Включая и Исключая. Если указано значение Включая, значит в
интервале будет использоваться граничное значение. Если же указано
значение Исключая, то значит в интервале граничное значение применяться
не будет.
Таким образом, если нам нужен момент времени вместе с движением
документа, то нам нужно создать объект Граница следующим образом:
Новый Граница(Документ1.МоментВремени(),ВидГраницы.Включая)
Листинг 2.12.
Если же мы хотим, чтобы граница не включала в себя движения
документа на какой-то момент времени, то объект должен быть создан так:
Новый Граница(Документ1.МоментВремени(),ВидГраницы.Исключая)
Листинг 2.13.
Самостоятельно поменяйте код из листинга 2.11, чтобы получились
остатки, включая движения документов (см. рис. 2.53).
Для тренировки, можете реализовать оба варианта в одной обработке,
сделав, к примеру, переключатель.
Рис. 2.53.
44
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Теперь Вам должно быть понятно, почему мы применили объект
Граница в листинге 2.6 (см. стр. 34), когда вычисляли остатки после
проведения документа. По «новой методике» проведения документа, нам
нужно проверять остатки товаров уже после проведения документа, так,
чтобы значения этих остатков включали в себя движения проведенного
документа. Корректно получить остатки вместе с движениями текущего
документа можно, только используя объект Граница, где в качестве значения
интервала указывается момент времени этого документа, а вид границы
будет иметь значение Включая.
Многоскладской учет
В какой-то момент наш заказчик расширился и сделал несколько залов в
магазине. Теперь заказчику необходимо стало знать, сколько какого товара
хранится в каждом зале магазина.
Для этих целей мы реализуем
многоскладской учет в нашей организации.
Для этого в нашей конфигурации создадим простой не иерархический
справочник «Склады».
Рис. 2.54.
Сейчас нам нужно решить, как мы будем дорабатывать регистр
накопления «Остатки товаров». Очевидно, что у нас добавилась новая
аналитика хранения ресурса. Если изначально наш ресурс собирался по
измерению Товар, т.е. товаров становилось или больше или меньше, то
теперь у нас товаров становится больше или меньше в конкретном торговом
зале (складе), добавилась дополнительная аналитика. Аналитика ресурсов в
45
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
регистрах накопления хранится в измерениях, поэтому добавим новое
измерение Склад (тип ссылка на справочник Склады).
Рис. 2.55.
Доработаем документы прихода и расхода. В случае прихода и расхода
один документ будет осуществлять поступление (или убытие) товара только с
одного склада. Поэтому у обоих документов создадим реквизит Склад с
соответствующим типом (синоним реквизита в обоих случаях «Торговый
зал»).
Рис. 2.56.
Для документа Приход создайте реквизит, и скопируйте его в документ
Расход.
46
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.57.
Доработаем журнал документов ПриходРасход: добавим новую графу
Склад (синоним «Торговый зал») с типом ссылка на справочник Склады.
Рис. 2.58.
Конфигурацию мы сконструировали, теперь осталось изменить
проведение документов. Начнем с документа Приход. Зайдем в модуль
объекта документа. В цикле, где идет обход табличной части, добавим
строку, в которой свойству Склад записи регистра накопления будем
присваивать значение из реквизита Склад документа.
47
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Процедура ОбработкаПроведения(Отказ, Режим)
// регистр ОстаткиТоваров Приход
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаСписокТоваров Из СписокТоваров Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
//++складской учет
Движение.Склад = Склад;
//
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
КонецЦикла;
КонецПроцедуры
Листинг 2.14.
Изменим проведение документа Расход. Откроем модуль объекта
документа и сделаем в нем следующие изменения.
В том месте, где мы записываем данные в регистр накопления «Остатки
товаров» (листинг 2.5), добавим строку, в которой свойству Склад записи
регистра накопления будем присваивать значение из реквизита Склад
документа.
Движения.ОстаткиТоваров.Записывать = Истина;
Пока Выборка.Следующий() Цикл
НовоеДвижение = Движения.ОстаткиТоваров.Добавить();
ЗаполнитьЗначенияСвойств(НовоеДвижение,Выборка);
НовоеДвижение.ВидДвижения = ВидДвиженияНакопления.Расход;
НовоеДвижение.Период = Дата;
//+++ Складской учет
НовоеДвижение.Склад = Склад;
///
КонецЦикла;
Движения.ОстаткиТоваров.Записать();
Листинг 2.15.
Следующим шагом запись со складом будет добавляться в регистр
накопления. Осталось сделать так, чтобы проверка остатков после
проведения контролировала наличие товара на конкретном складе. Для
этого переделаем запрос, в котором мы осуществляем контроль остатков
(см. листинг 2.6).
Откроем конструктор запроса для этого запроса и сделаем следующие
изменения.
48
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Первое. Добавим параметр &Склад в отбор из временной таблицы
ДокТЧ.
Рис. 2.59.
Второе. Добавим представление параметра &Склад.
Рис. 2.60.
У нас должен получиться следующий запрос.
//контроль остатков
Запрос.Текст = "ВЫБРАТЬ
|
ПРЕДСТАВЛЕНИЕ(ДокТЧ.Товар) КАК Товар,
|
- ЕСТЬNULL(ОстаткиТоваровОстатки.КоличествоОстаток, 0)
КАК Остаток,
|
ПРЕДСТАВЛЕНИЕ(&Склад) КАК Склад
|ИЗ
|
ДокТЧ КАК ДокТЧ
|
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрНакопления.ОстаткиТоваров.Остатки(
|
&МоментВремени,
|
(Товар, Склад) В
|
(ВЫБРАТЬ
|
вт.Товар,
|
&Склад
|
ИЗ
|
ДокТЧ КАК вт)) КАК
ОстаткиТоваровОстатки
|
ПО ДокТЧ.Товар = ОстаткиТоваровОстатки.Товар";
Запрос.УстановитьПараметр("МоментВремени",
49
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
?(РежимПроведения =
РежимПроведенияДокумента.Оперативный,
Новый
Граница(МоментВремени(),ВидГраницы.Включая),
Неопределено));
Запрос.УстановитьПараметр("Склад",Склад);
Листинг 2.16.
В параметр &Склад запроса передано значение одноименного
реквизита документа.
Нам осталось изменить сообщение, которое выводится при недостатке
товара, таким образом, чтобы выводился еще и нужный склад.
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.Остаток > 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Товара " + Выборка.Товар + " на складе " +
Выборка.Склад + " не хватает " + Выборка.Остаток;
Сообщение.Сообщить();
Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Листинг 2.17.
Всё! На этом доработка документов окончена. Теперь проверим, как
работает наша конфигурация. Создадим три склада (торговых зала).
Рис. 2.61.
Сделаем приходы по молочному, хлебному и овощному отделам.
50
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.62.
Рис. 2.63.
Рис. 2.64.
51
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Попробуем в хлебном отделе продать сметану.
Рис. 2.65.
Программа выдала ошибку, что в этом отделе нет товара Сметана.
Если мы попытаемся помимо сметаны продать хлеба больше, чем
имеется на складе, то будет выведено сообщение, что нет ни нужного
количества хлеба, ни нужного количества сметаны.
Рис. 2.66.
52
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Таким образом, у нас одновременно осуществляется контроль остатков,
как в разрезе товаров, так и в разрезе складов.
Показываем остатки на форме списка номенклатуры
Сделаем нашу конфигурацию более удобной: будем показывать остатки
по номенклатуре на форме списка справочника Номенклатура. Сейчас, у
этого справочника нет ни каких форм, поэтому создадим форму списка.
Рис. 2.67.
При создании, выберем только поля Код и Наименование.
53
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.68.
У нас будет создана форма с динамическим списком в качестве
реквизита. Вот этот динамический список мы и переделаем.
Рис. 2.69.
Откроем палитру свойств этого динамического списка и установим флаг
«Произвольный запрос».
54
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.70.
После установки флага, нажмем гиперссылку «Открыть» рядом со
свойством «Настройка Списка», откроется окно с уже созданным запросом.
Рис. 2.71.
Нажмем на кнопку «Конструктор запроса…» в окне «Динамический
список» и переделаем наш запрос. Выберем таблицу остатков регистра
сведений ОстаткиТоваров, у виртуальной таблицы выберем поле
55
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
КоличествоОстаток, свяжем левым соединением таблицу справочника
Номенклатура с таблицей остатков регистра накопления ОстаткиТоваров,
и переименуем поле КоличествоОстаток в Остаток.
Рис. 2.72.
Рис. 2.73.
Рис. 2.74.
Всё. Запрос мы переделали, сохраним настройку динамического списка
и «перетащим» поле Остаток в таблицу Список на форме списка.
Рис. 2.75.
56
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Вроде бы задача сделана, но мы реализовали в нашей конфигурации
многоскладской учет. Получается, что остатки мы видим сразу по всем
складам, что, конечно, интересно, но абсолютно не информативно. Сделаем
так, чтобы на этой форме можно было видеть еще и остатки по складам.
Реализуем мы это следующим образом: создадим на форме новый реквизит
с типом ДинамическийСписок, в котором будем выводить остатки в разрезе
складов, но с отбором по товару, который будем передавать в этот список
при активизации строки основного списка.
Создадим реквизит с типом ДинамическийСписок, который назовем
ОстаткиПоСкладам. В палитре свойств динамического списка установим флаг
рядом со свойством «Произвольный запрос».
Рис. 2.76.
Откроем настройку списка и создадим простой запрос, в котором
выберем
виртуальную
таблицу
Остатки
регистра
накопления
ОстаткиНоменклатуры.
57
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.77.
Теперь нам нужно сделать так, чтобы работал отбор по товару, но
необходимо учесть, что если товар не передан в качестве параметра (такое
может быть, когда нет ни одного товара), то не возникало ошибки. Поэтому
установим отбор не в параметрах виртуальной таблицы, а в компоновке
данных. Для этого, откроем конструктор запроса, перейдем на вкладку
«Компоновка данных», откроем в ней параметры виртуальной таблицы
остатков, где и установим отбор по измерению Товар.
Рис. 2.78.
У нас должен получиться следующий запрос в динамическом списке.
ВЫБРАТЬ
ОстаткиТоваровОстатки.Склад КАК Склад,
ОстаткиТоваровОстатки.КоличествоОстаток КАК Остаток
ИЗ
РегистрНакопления.ОстаткиТоваров.Остатки(, {(Товар = &Товар)}) КАК
ОстаткиТоваровОстатки
Листинг 2.18.
58
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Динамический список мы создали, теперь перенесем его на форму в
виде таблицы.
Рис. 2.79.
Форму мы доработали, теперь осталось сделать так, чтобы при
выделении строки в таблице Список обновлялись данные в таблице
ОстаткиПоСкладам. Для этого создадим событие ПриАктивизацииСтроки
(на клиенте) таблицы формы Список.
Рис. 2.80.
В обработчике события напишем следующий код. Первым делом будем
выходить из обработчика, если текущая строка таблицы Список равна
Неопределено, такое может быть, если нет данных в списке.
59
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
Если Элементы.Список.ТекущаяСтрока = Неопределено Тогда
Возврат
КонецЕсли;
КонецПроцедуры
Листинг 2.19.
Теперь нам нужно сделать защиту от зацикливания. Дело в том, что
событие таблицы ПриАктивизацииСтроки возникает не только при
активизации строки таблицы, но и при других действиях с формой. Чтобы у
нас лишний раз не срабатывала установка отбора, создадим глобальную
переменную формы и будем проверять, равна ли текущая строка таблицы
Список (это будет ссылка на элемент справочника) этой переменной, если
равна, то мы выйдем из процедуры, а если нет, то присвоим этой
переменной значение текущей строки таблицы.
&НаКлиенте
Перем ТекНомен;
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
Если Элементы.Список.ТекущаяСтрока = Неопределено Тогда
Возврат
КонецЕсли;
Если ТекНомен = Элементы.Список.ТекущаяСтрока тогда
Возврат;
КонецЕсли;
ТекНомен = Элементы.Список.ТекущаяСтрока;
КонецПроцедуры
Листинг 2.20.
Нам осталось передать параметр в динамический список, сделать это
можно только в серверном контексте, поэтому сделаем процедуру в
серверном контексте и будем ее вызывать в событии.
&НаКлиенте
Перем ТекНомен;
&НаСервере
Процедура УстановитьЗначениеПараметраДинамическогоСписка(Номенклатура)
ОстаткиПоСкладам.Параметры.УстановитьЗначениеПараметра("Товар",Номенклатура);
КонецПроцедуры
60
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
Если Элементы.Список.ТекущаяСтрока = Неопределено Тогда
Возврат
КонецЕсли;
Если ТекНомен = Элементы.Список.ТекущаяСтрока тогда
Возврат;
КонецЕсли;
ТекНомен = Элементы.Список.ТекущаяСтрока;
УстановитьЗначениеПараметраДинамическогоСписка(ТекНомен);
КонецПроцедуры
Листинг 2.21.
Всё, осталось проверить, как работает наша форма.
Рис. 2.81.
61
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Отчет «Остатки товаров на складах»
Создадим отчет, в котором оператор может посмотреть остатки товара в
разрезе складов. Назовем его «Остатки товаров на складах».
Рис. 2.82.
Создадим схему компоновки этого отчета, нажав на кнопку «Открыть
схему компоновки данных». В открывшейся схеме компоновки данных,
добавим набор данных запрос.
Рис. 2.83.
Создадим запрос, в котором выберем виртуальную таблицу Остатки
регистра накопления ОстаткиТоваров, а также поля Склад, Товар и
КоличествоОстаток.
62
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.84.
Поля заполнятся автоматически. Исправим заголовок
КоличествоОстаток на Остаток, и добавим это поле в ресурсы.
поля
Рис. 2.85.
63
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.86.
Перейдем на закладку «Настройки», добавим группировку «Склад» и
группировку с детальными записями.
Рис. 2.87.
Рис. 2.88.
Рис. 2.89.
64
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
На группировке «Детальные записи» в настройке «Отчет» в закладке
«Выбранные поля» добавим поля Склад, Товар и КоличествоОстаток.
Рис. 2.90.
Для отчета в других настройках отключим расположение общих итогов
по вертикали.
Рис. 2.91.
Нам осталось добавить параметр Период в пользовательские настройки,
и наш отчет готов.
65
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 2.92.
Проверим, как он работает.
Рис. 2.93.
66
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Задания для самостоятельной работы
1)
2)
3)
4)
5)
6)
Создайте документ, который будет осуществлять перемещение товара
между складами, контролируйте остатки товара на складе, с которого он
будет браться;
Сделайте так, чтобы при открытии формы элемента справочника
«Номенклатура», показывались остатки этой номенклатуры в разрезе
складов;
Добавьте реквизит Склад в табличную часть документов Приход и
Расход. Измените проведение документа так, чтобы брался склад из
табличной части;
Разработайте систему учета денежных средств. Для этого. Создайте
новый справочник Кассы. Доработайте документы Приход и Расход:
добавьте реквизиты СуммаПрихода (СуммаРасхода) и КассаПрихода
(КассаРасхода).
Создайте
новый
регистр
накопления
ОстатокДенежныхСредств,
при
помощи
которого
будете
контролировать остаток денежных средств в кассах (структуру
продумайте
сами).
Также
создайте
новый
документ
ВнесениеДенежныхСредствВКассы, который необходимо создавать,
когда денежные средства вносятся в кассу помимо случаев продажи. И
наоборот, создайте документ
ИзъятиеДенежныхСредствИзКасс,
который следует создавать, когда денежные средства изымаются из
кассы помимо случаев покупки; Сделайте проведение документов
Приход,
Расход,
ВнесениеДенежныхСредствВКассы
и
ИзъятиеДенежныхСредствИзКасс
по
регистру
накопления
ОстатокДенежныхСредств с контролем остатков при списании;
В справочнике Кассы исправьте форму списка так, чтобы показывался
остаток по кассе;
На основе созданной конфигурации, разработайте конфигурации, где
контроль остатков будет осуществляться по «старой методике»: сначала
будет осуществляться контроль остатка, и если остатков хватает, то
делаются движения по регистру накопления. Обратите внимание на
использование момента времени (или границы) при выполнении
запроса по контролю остатков.
67
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Глава 3. Реализуем суммовой учет
Суммовой учет осуществляется тогда, когда, помимо, количественных
остатков товаров на складе нужно знать и суммовой остаток (в валюте учета).
Как правило, в торговых организациях суммовой учет ведется по закупочным
ценам, таким образом, суммовые остатки товаров отображают их
себестоимость.
Постановка задачи
Оптовая фирма осуществляет торговлю различными товарами. У фирмы
имеется несколько складов, разбросанных по разным частям города. Товары
поступают на склады, а потом реализуются. Необходимо разработать
конфигурацию, в которой осуществляется товарный учет: фиксируется какое
количество товаров по какой цене было оприходовано, а потом фиксируется
продажа товара по какой-то цене. Необходимо осуществлять контроль
наличия товара на складе: если товара нет, то отгрузить его нельзя.
Менеджерам нужно знать не только количественный остаток на складе, но и
суммовой, чтобы знать, по какой цене продавать товар и не быть в убытке.
Также менеджеры должны обладать информацией о себестоимости товара и
о валовой прибыли (выручка минус себестоимость).
Способы ведения суммового учета
Прежде чем начать разрабатывать конфигурацию и реализовывать
суммовой учет, изучим, какие способы ведения суммового учета существуют.
Мы разберем три способа: по средней себестоимости, по FIFO и по LIFO.
По средней себестоимости
Данный вид ведения суммового учета является самым доступным для
понимания. При этом способе, во время поступления товара увеличивается
суммовой и количественный показатель в независимости от склада. Во
время же списания товара, общую сумму делят на общее количество, тем
68
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
самым получая среднюю стоимость единицы товара. Таким образом,
себестоимость списания товара рассчитывается следующим образом:
Себестоимость = Общая сумма / Общее количество * Количество на
списание;
Рассмотрим простой пример.
Было три прихода товара по разной цене.
Товар
Количество
Сумма
Валенки
10
200
Валенки
20
200
Валенки
10
400
Табл. 3.1.
Теперь списываем 15 штук: Сумма списания = (200 + 200 + 400 ) / (10 + 20 +
10) * 15 = 300
Товар
Количество
Сумма
Валенки
15
300
Табл. 3.2.
У нас осталось 25 штук общей стоимостью: 800 – 300 = 500.
Списываем еще 20 штук: 500 / 25 * 20 = 400.
Товар
Количество
Сумма
Валенки
20
400
Табл. 3.3.
У нас осталось 5 штук общей стоимостью 500 – 400 = 100.
И списываем остаток 5 штук: 100 / 5 * 5 = 100.
69
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Товар
Количество
Сумма
Валенки
5
100
Табл. 3.4.
По FIFO, по LIFO
Способы расчета себестоимости по FIFO и по LIFO применяются, когда
учет товаров ведется по партиям (партионный учет). Партия товаров это
однородный товар, поступивший по одному транспортному документу
(накладная, документ оприходования и т.п).
Существует несколько способов ведения партионного учета. Мы
рассмотрим только два:
FIFO (First In First Out) – первый пришел, первый ушел – означает, что первым
делом списываются партии товаров, которые поступили первые (самые
старые).
LIFO (Last In First Out) – последний пришел, первый ушел – означает, что
сначала списываются партии товаров, которые поступили последними
(самые ранние).
Рассмотрим наглядно принцип ведения партионного учета.
упрощения сделаем, что партия товара это документ прихода.
Для
У нас было три документа прихода товара с разными ценами:
Товар
Количество
Сумма
Партия
Валенки
2
200
Приход 1
Калоши
1
150
Приход 1
Валенки
3
150
Приход 2
Калоши
2
200
Приход 2
Валенки
4
600
Приход 3
Табл. 3.5.
70
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Разберем, как происходит списание (метод FIFO).
Допустим, в первом расходе мы продали одну пару валенок, и две пары
калош.
Товар
Количество
Сумма
Партия
Валенки
1
200/2 * 1 = 100
Приход 1
Калоши
1
150/1 * 1 = 150
Приход 1
Калоши
1
200/2 * 1 = 150
Приход 2
Табл. 3.6.
Во втором расходе мы продали три пары валенок и одну пару калош.
Товар
Количество
Сумма
Партия
Валенки
1
200/2 * 1 = 100
Приход 1
Валенки
2
150/3 * 2 = 100
Приход 2
Калоши
1
200/2 * 1 = 100
Приход 2
Табл. 3.7.
Таким образом, мы видим, как у нас происходит расчет себестоимости
при ведении партионного учета. Себестоимость храниться в разрезе партий,
т.е. для каждой партии товара рассчитывается своя себестоимость, которая
потом списывается. Если товара при списании больше чем в первой партии,
то сначала списывается то количество, которое имеется в первой партии и
для него рассчитывается себестоимость. А оставшееся количество
списывается по следующей партии, и для него рассчитывается уже новая
себестоимость.
Посмотрим, как будет выглядеть списание партий при методе LIFO.
71
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
В первом расходе мы продали одну пару валенок, и две пары калош.
Товар
Количество
Сумма
Партия
Валенки
1
600/4 * 1 = 150
Приход 3
Калоши
2
200/2 * 2 = 200
Приход 2
Табл. 3.8.
Во втором расходе мы продали три пары валенок и одну пару калош.
Товар
Количество
Сумма
Партия
Валенки
3
600/4 * 3 = 450
Приход 3
Калоши
1
150/1 * 1 = 150
Приход 1
Табл. 3.9.
Разработка конфигураций
По средней себестоимости
Сделаем новую конфигурацию, на базе конфигурации, где мы
реализовывали количественный оперативный учет для суммового учета по
средней себестоимости. Из конфигурации, сделанной в предыдущей главе,
выгрузим cf-файл.
Для этого войдем в конфигуратор, и в меню
Конфигурация воспользуемся командой «Сохранить конфигурацию в
файл…».
72
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.1.
Теперь создадим пустую базу, как это мы делали в начале предыдущей
главы, и загрузим в нее cf-файл, выгруженный ранее. Для этого
воспользуемся командой «Загрузить конфигурацию из файла…» в уже
знакомом нам меню Конфигурация.
Конфигурация загружена, переименуем имя конфигурации в «Суммовой
оперативный учет», воспользовавшись уже знакомым нам по предыдущей
главе свойствам конфигурации.
Рис. 3.2.
Ни чего больше менять не будем, а давайте подумаем, как нам нужно
доработать конфигурацию, чтобы учитывать суммовой остаток на складе. И,
конечно же, первое что приходит на ум – добавить ресурс Сумма в уже
сделанный регистр накопления «Остатки».
73
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.3.
Сейчас я покажу, почему это плохая идея. Пусть у нас было два прихода
валенок на разные склады (для простоты в таблице ниже отбросим
измерение «Товар»).
Регистратор
Склад
Количество
Сумма
Приход 1
Первый
2
300
Приход 2
Второй
3
100
Табл. 3.10.
Теперь спишем две штуки валенок с первого склада. Себестоимость
будем рассчитывать «по средней» для всех складов!
Регистратор
Склад
Количество
Сумма
Расход 1
Первый
2
(300+100)/(2+3)
* 2 = 160
Табл. 3.11.
После этого у нас на первом складе останется 0 валенок на сумму 300 –
160 = 140. Что уже является грубейшей ошибкой учета!
74
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Если мы сейчас спишем три штуки со второго склада.
Регистратор
Склад
Количество
Сумма
Расход 2
Второй
3
(140+100)/(0 +
3) * 3 = 240
Табл. 3.12.
То на втором складе останется 0 валенок на сумму 100 – 240 = -140.
Наша конфигурация работает не корректно!
Для того, чтобы наша конфигурация работала корректно, добавим
новый регистр накопления Себестоимость (остатки).
Рис. 3.4.
У которого, будет одно измерение – Товар (тип ссылка на справочник
Номенклатура), и два ресурса – Количество и Сумма (тип Число(10,2)).
75
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.5.
Также как и в случае регистра остатков, у этого регистра будет два
регистратора – документы Приход и Расход.
Рис. 3.6.
Изменим документы Приход и Расход, добавив в табличные части поле
Сумма (Число (10,2)).
76
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.7.
Всё! Регистр мы сделали, документы переделали, займемся
проведением документов. Первым делом, добавим движения документа
Приход. Для этого в модуле документа изменим код в процедуре
ОбработкаПроведения.
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Себестоимость.Записывать = Истина;
Для Каждого ТекСтрокаСписокТоваров Из СписокТоваров Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
//++складской учет
Движение.Склад = Склад;
//
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
//по регистру себестоимости
Движение = Движения.Себестоимость.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
Движение.Сумма = ТекСтрокаСписокТоваров.Сумма;
//
КонецЦикла;
КонецПроцедуры
Листинг 3.1.
77
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Изменения должны вам быть понятны: мы добавили движения прихода
по регистру Себестоимость.
Перейдем к документу Расход. В модуле документа сделаем следующие
доработки. Первым делом, установим свойству Записывать набора записей
регистра накопления Себестоимость значение Истина.
//делаем движения по себестоимости
Движения.Себестоимость.Записывать = Истина;
Листинг 3.2.
Теперь, используя тот же самый объект запрос, который мы сделали
ранее (где создали временную таблицу и выполнили контроль остатков),
напишем новый запрос. Откроем конструктор запроса для этого запроса и
сделаем следующие изменения.
Создадим временную таблицу ДокТЧ с полями Товар и Количество.
Рис. 3.8.
Сама временная таблица у нас создается и заполняется ранее (см. стр.
26).
Выберем виртуальную таблицу
Себестоимость.
Остатки регистра накопления
Рис. 3.9.
78
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
И соединим таблицу ДокТЧ с таблицей остатков по полю Товар левым
соединением.
Рис. 3.10.
Зайдем в параметры виртуальной таблицы остатков, уставим период, и
сделаем ограничение на выбор товаров: отберем только те товары, которые
имеются во временной таблице ДокТЧ.
Рис. 3.11.
Нам осталось выбрать поля, и запрос готов.
Рис. 3.12.
У нас должен получиться следующий запрос.
79
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Запрос.Текст = "ВЫБРАТЬ
|
ДокТЧ.Товар КАК Товар,
|
ДокТЧ.Количество КАК Количество,
|
ЕСТЬNULL(СебестоимостьОстатки.КоличествоОстаток, 0) КАК
КоличествоОстаток,
|
ЕСТЬNULL(СебестоимостьОстатки.СуммаОстаток, 0) КАК
СуммаОстаток
|ИЗ
|
ДокТЧ КАК ДокТЧ
|
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрНакопления.Себестоимость.Остатки(
|
&Период,
|
Товар В
|
(ВЫБРАТЬ
|
ДокТЧ.Товар
|
ИЗ
|
ДокТЧ КАК ДокТЧ)) КАК
СебестоимостьОстатки
|
ПО ДокТЧ.Товар = СебестоимостьОстатки.Товар";
Листинг 3.3.
Этот запрос нам вернет выборку товаров, которые имеются в документе,
сгруппированное количество из документа (данные из временной таблицы
ДокТЧ), остаток по количеству и остаток по сумме в регистре накопления
Себестоимость для соответствующих товаров.
Передадим параметры в запрос и сделаем выборку.
Запрос.УстановитьПараметр("Период",МоментВремени());
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Листинг 3.4.
Обратите внимание, что я передаю момент времени в качестве периода,
т.к. нам не нужно учитывать движения этого документа (как мы делали при
контроле остатков).
Обойдем выборку, где в процессе каждой итерации будем создавать
новую запись регистра накопления Себестоимость.
Пока Выборка.Следующий() Цикл
Если Выборка.КоличествоОстаток = 0 Тогда
//что-нибудь сообщаем
Продолжить;
КонецЕсли;
Движение = Движения.Себестоимость.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
80
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Движение.Товар = Выборка.Товар;
Движение.Количество = Выборка.Количество;
Движение.Сумма = Выборка.СуммаОстаток / Выборка.КоличествоОстаток *
Выборка.Количество ;
КонецЦикла;
Листинг 3.5.
В последней строке в теле цикла мы получаем себестоимость списания:
получаем себестоимость остатка одной единицы товара, поделив сумму
остатка на оставшееся количество товара, а потом умножаем себестоимость
одной единицы на количество, которое в документе.
Данный код теоретически правильный, но на практике иногда
возникают проблемы при округлении (теряются или прибавляются копейки).
Поэтому в том случае, когда количество в остатке равно количеству в
документе целесообразнее сразу записывать сумму остатка, без лишних
движений.
Код в этом случае будет следующий.
Если
Выборка.Количество = Выборка.КоличествоОстаток Тогда
Движение.Сумма = Выборка.СуммаОстаток;
Иначе
Движение.Сумма = Выборка.СуммаОстаток / Выборка.КоличествоОстаток *
Выборка.Количество ;
КонецЕсли;
Листинг 3.6.
Проверим работу нашего кода. Создадим документ прихода по одному
складу.
81
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.13.
И по другому складу.
Рис. 3.14.
Теперь сделаем три расхода (сумма расхода пока не критична), один по
первому складу, и два по второму.
Рис. 3.15.
82
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.16.
Рис. 3.17.
Посмотрим, что у нас записалось в регистр. Поскольку ни каких отчетов
еще не сделано, то откроем регистр напрямую через меню «Все функции».
Рис. 3.18.
Все списалось вполне корректно. Можете сами вручную проверить.
83
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Партионный учет
Создадим новую базу для реализации партионного учета. За основу,
также, возьмем базу из второй главы, где мы реализовывали
количественный учет, только переименуем имя конфигурации.
Рис. 3.19.
В этой базе создадим регистр накопления (вид остатки) ПартииТоваров.
Рис. 3.20.
Создадим два измерения Товар (тип ссылка на справочник
Номенклатура) и Партия (тип ссылка на документ Приход), а также два
ресурса – Количество и Сумма (тип Число(10,2)).
84
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.21.
Также у регистра будет два регистратора, документы Приход и Расход.
Рис. 3.22.
Не забудем создать реквизиты Сумма в табличных частях документов
Приход и Расход.
85
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.23.
На этом работы, связанные с конфигурированием для расчета партий,
закончим. Нам осталось реализовать возможность применения методов FIFO
и LIFO в нашей конфигурации. Способ ведения учета будет задаваться в
учетной политики организации, и его можно менять раз в год.
Создадим перечисление ВидПолитики со значениями ФИФО и ЛИФО.
Рис. 3.24.
Создадим регистр сведений УчетнаяПолитика с периодичностью в год,
где в ресурсе будем хранить значение перечисления ВидПолитики.
86
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.25.
Рис. 3.26.
Создадим общий модуль УчетнаяПолитикаСервер (установлен флаг
Сервер), у которого в свойство «Повторное использование возвращаемых
значений» установим значение «На время сеанса».
Рис. 3.27.
И в этом модуле напишем функцию, которая будет возвращать текущее
значение вида политики.
87
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Функция ВернутьВидПартионногоУчета(ДатаДок) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|
УчетнаяПолитикаСрезПоследних.ВидПолитики КАК
ВидПолитики
|ИЗ
|
РегистрСведений.УчетнаяПолитика.СрезПоследних(&ДатаДок, ) КАК
УчетнаяПолитикаСрезПоследних";
Запрос.УстановитьПараметр("ДатаДок",ДатаДок);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат Неопределено;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
ВидУчПолитики = Выборка.ВидПолитики;
Возврат ВидУчПолитики;
КонецФункции
Листинг 3.7.
В этом коде мы получаем срез последних записей регистра сведений
УчетнаяПолитика на некую дату (это будет дата документа, в котором нам
понадобится узнать вид политики), а потом получаем значение ресурса
регистра (если оно имеется).
Этап конфигурирования мы закончили, теперь займемся проведением
документов. Первый документ это документ Приход. Изменим код в
процедуре ОбработкаПроведения в модуле этого документа следующим
образом.
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.ПартииТоваров.Записывать = Истина;
Для Каждого ТекСтрокаСписокТоваров Из СписокТоваров Цикл
// регистр ОстаткиТоваров Приход
Движение = Движения.ОстаткиТоваров.Добавить();
//++складской учет
Движение.Склад = Склад;
//
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
//регистр ПартииТоваров Приход
Движение = Движения.ПартииТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
88
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Движение.Товар = ТекСтрокаСписокТоваров.Номенклатура;
Движение.Количество = ТекСтрокаСписокТоваров.Количество;
Движение.Сумма = ТекСтрокаСписокТоваров.Сумма;
Движение.Партия = Ссылка;
КонецЦикла;
КонецПроцедуры
Листинг 3.8.
Нет ни чего сложного в этом коде – мы свойству Партия записи
регистра накопления ПартииТоваров присваиваем значение ссылки на
документ.
Нам осталось сделать доработку проведения для документа расход.
Перейдем к документу Расход. В модуле документа сделаем следующие
доработки. Первым делом, установим свойству Записывать набора записей
регистра накопления ПартииТоваров значение Истина.
Движения.ПартииТоваров.Записывать = Истина;
Листинг 3.9.
Определим текущий вид учетной политики, для этого воспользуемся
уже
ранее
созданной
в
общем
модуле
функций
ВернутьВидПартионногоУчета.
ВидПолитики = УчетнаяПолитикаСервер.ВернутьВидПартионногоУчета(Дата);
Если ВидПолитики = Неопределено Тогда
//что-нибудь сообщаем
Отказ = истина;
Возврат;
КонецЕсли;
Листинг 3.10.
Естественно, если у нас не установлена учетная политика на эту дату, то
нет смысла проводить документ.
Теперь, используя тот же самый объект запрос, который мы сделали
ранее (где создали временную таблицу и выполнили контроль остатков),
напишем новый запрос. Откроем конструктор запроса для этого запроса и
сделаем следующие изменения.
Создадим временную таблицу ДокТЧ с полями Товар и Количество.
89
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.28.
Сама временная таблица у нас создается и заполняется ранее (см. стр.
26).
Выберем виртуальную
ПартииТоваров.
таблицу
Остатки
регистра
накопления
Рис. 3.29.
Соединим таблицу ДокТЧ с таблицей остатков по полю Товар левым
соединением.
Рис. 3.30.
Зайдем в параметры виртуальной таблицы остатков, уставим период, и
сделаем ограничение на выбор товаров: отберем только те товары, которые
имеются во временной таблице ДокТЧ.
90
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.31.
Выберем поля Товар и Количество из таблицы ДокТЧ, а также поля
Партия, КоличествоОстаток и СуммаОстаток таблицы остатков.
Рис. 3.32.
Сделаем сортировку по дате партии.
Рис. 3.33.
Пока мы сделали сортировку по возрастанию, т.е первым делом идут
самые ранние документы прихода, т.е. реализуется метод FIFO. Ниже мы
сделаем так, чтобы сортировка зависела от вида политики.
В процессе работы, у нас может возникнуть ситуация, что при продаже
какого-то количества товара в одном расходе необходимо несколько партий
91
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
для его списания. Нам нужно получить иерархическую выборку, где вверху
иерархии будет товар, который списывается, а в детальных записях
непосредственно партии, которые есть в остатках. Для этого выполним итоги
по полю Товар, а для поля Количество в итогах применим агрегатную
функцию Максимум.
Рис. 3.34.
Всё, на этом мы закончим конструировать запрос, он должен получиться
такого вида.
Запрос.Текст = "ВЫБРАТЬ
|
ДокТЧ.Товар КАК Товар,
|
ДокТЧ.Количество КАК Количество,
|
ЕСТЬNULL(ПартииТоваровОстатки.Партия,
ЗНАЧЕНИЕ(Документ.Приход.ПустаяСсылка)) КАК Партия,
|
ЕСТЬNULL(ПартииТоваровОстатки.КоличествоОстаток, 0)
КАК КоличествоОстаток,
|
ЕСТЬNULL(ПартииТоваровОстатки.СуммаОстаток, 0) КАК
СуммаОстаток
|ИЗ
|
ДокТЧ КАК ДокТЧ
|
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрНакопления.ПартииТоваров.Остатки(
|
&Период,
|
Товар В
|
(ВЫБРАТЬ
|
вт.Товар
|
ИЗ
|
ДокТЧ КАК вт)) КАК
ПартииТоваровОстатки
|
ПО ДокТЧ.Товар = ПартииТоваровОстатки.Товар
|
|УПОРЯДОЧИТЬ ПО
|
ПартииТоваровОстатки.Партия.Дата
|ИТОГИ
|
МАКСИМУМ(Количество)
|ПО
|
Товар";
Листинг 3.11.
92
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Сделаем
теперь
так,
чтобы
выражение
ПартииТоваровОстатки.Партия.Дата в конструкции УПОРЯДОЧИТЬ
ПО было или по возрастанию, если вид политики ФИФО, или по убыванию,
если вид политики ЛИФО.
Вид политики мы уже получили, осталось просто заменить выражение в
тексте запроса на нужное в зависимости от того или иного вида.
Запрос.Текст = СтрЗаменить(Запрос.Текст,"ПартииТоваровОстатки.Партия.Дата",
?(ВидПолитики =
Перечисления.ВидПолитики.ФИФО,"ПартииТоваровОстатки.Партия.Дата
ВОЗР","ПартииТоваровОстатки.Партия.Дата УБЫВ"));
Листинг 3.12.
Установим параметр Период (это будет момент времени документа,
поскольку учитывать движения документа нам не нужно, в отличие от
контроля остатков), получим результат запроса, получим выборку по
группировке Товар и сделаем обход выборки в цикле.
Запрос.УстановитьПараметр("Период",МоментВремени());
Результат = Запрос.Выполнить();
ВыборкаТовар =
Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам,"Товар");
Пока ВыборкаТовар.Следующий() Цикл
КонецЦикла;
Листинг 3.13.
В теле цикла зафиксируем количество, которое нужно списать, получим
выборку по партиям (прямую) и начнем обходить эту выборку.
Списывать = ВыборкаТовар.Количество;
ВыборкаПартия = ВыборкаТовар.Выбрать(ОбходРезультатаЗапроса.Прямой);
Пока ВыборкаПартия.Следующий() Цикл
КонецЦикла;
Листинг 3.14.
Количество, которое нужно списать (переменная Списывать) мы будем
в каждой итерации цикла уменьшать на количество, которое было списано.
Если в какой-то момент эта переменная станет равна 0, то мы прервем
выполнение цикла.
93
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
В цикле выборки по партиям мы будем действовать по следующему
алгоритму.
1)
2)
3)
4)
5)
Найдем количественный остаток по партии;
Из количественного остатка по партии и количества, которое нужно
списать, выберем то, что меньше. Именно это количество будет списано;
Получим сумму на списание, как сумму остатка по партии деленное на
количество остатка по партии, и все это умноженное на количество,
которое идет на списание (полученное в п.2);
Полученную сумму на списание и количество на списание записываем в
регистр накопления.
Поскольку партий может быть несколько и первая партия в цикле может
сразу не списать все количество из документа, то уменьшаем количество
на списание на величину того количества, которое было списано.
Получится следующий код.
Пока ВыборкаПартия.Следующий() Цикл
//проверим осталось ли что на списывание
Если Списывать <= 0 Тогда
Прервать;
КонецЕсли;
Если ВыборкаПартия.КоличествоОстаток = 0 Тогда
//что-нибудь сообщаем
Продолжить;
КонецЕсли;
//получим количество, которое в конкретной партии
КоличествоВПартии = ВыборкаПартия.КоличествоОстаток;
//определим что будем списывать, количество из партии
//или оставшееся количество на списание
СписыватьПартию = Мин(Списывать,КоличествоВПартии);
//защита от проблем с округлением
Если СписыватьПартию = ВыборкаПартия.КоличествоОстаток Тогда
СуммаПартии = ВыборкаПартия.СуммаОстаток;
иначе
СуммаПартии = (ВыборкаПартия.СуммаОстаток /
ВыборкаПартия.КоличествоОстаток ) * СписыватьПартию;
КонецЕсли;
//делаем движения по документу
Движение = Движения.ПартииТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Товар = ВыборкаТовар.Товар;
Движение.Партия = ВыборкаПартия.Партия;
Движение.Количество = СписыватьПартию;
Движение.Сумма = СуммаПартии;
Списывать = Списывать - СписыватьПартию;
КонецЦикла;
Листинг 3.15.
94
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Всё! Нам осталось сохранить конфигурацию и проверить, как работает
списание по партиям. Для проверки реализуем примеры из таблиц 3.5 – 3.9.
Первым делом проверим работу метода FIFO, установим его в учетной
политике.
Рис. 3.35.
Теперь сделаем три прихода, согласно таблице 3.5.
Рис. 3.36.
Рис. 3.37.
95
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.38.
Теперь сделаем расходы, согласно таблицам 3.6 и 3.7 (количество по
номенклатуре сгруппируем).
Рис. 3.39.
Рис. 3.40.
Все документы созданы и проведены, проверим, как прошло списание.
Посмотрим на записи регистра ПартииТоваров.
96
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.41.
Все списалось как надо. Самостоятельно проверьте метод ЛИФО, перед
этим отменив проведение документов Расход.
Учет цен
Разработаем интерфейс для работы с ценами в нашей конфигурации.
Начнем разработку с создания реквизитов Цена (тип Число(10,2)) у
табличной части документов Приход и Расход.
Рис. 3.42.
Рис. 3.43
Подумаем, как мы будем осуществлять хранение цен номенклатуры.
Первое. Очевидно, что цены могут быть разных видов. Может быть цена
закупки, а может быть цена продажи. Первое что приходит на ум
использовать перечисления, но возможно пользователь захочет добавить
новые виды цен, и каждый раз придется менять конфигурацию. Поэтому, все
возможные варианты цен будем хранить в справочнике ВидыЦен, в котором
97
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
сделаем два предопределенных элемента Закупочная и Продажная. Цены с
видом Закупочная будут использоваться при работе с документом Приход, а
цены с видом Продажная – Расход.
Для продвинутых: сделайте константы «Вид цены для закупки» и «Вид
цены для продажи», в которых будут указаны соответствующие виды
цен, и именно эти константы используйте в дальнейшем при работе с
документами Приход и Расход.
Рис. 3.44.
Второе. Цены могут меняться со временем. У какого-то товара сегодня
может быть одна цена, завтра другая, а послезавтра - третья. Опять, первое,
что, может, придти Вам на ум - использовать справочник Номенклатура в
котором создать реквизит Цена. Но, во-первых, каждый раз, когда у нас
будет меняться цена номенклатуры, нам придется изменять элемент
справочника, тем самым будет потеряна история, во-вторых, нам придется
создавать кучу реквизитов под каждый вид цены, или делать отдельную
табличную часть. Поэтому, для целей работы с ценами удобно использовать
регистр сведений. Этот регистр сведений может быть, как независимым, так
и подчиненным регистратору. Мы сделаем регистр, который будет подчинен
регистратору. Для этого создадим документ УстановкаЦенНоменклатуры с
реквизитом ВидЦены (тип ссылка на справочник ВидыЦен), с табличной
частью СписокНоменклатур, у которой будут реквизиты Номенклатура (тип
ссылка на справочник Номенклатура) и Цена (тип Число(10,2)).
98
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.45.
Теперь создадим регистр сведений ЦеныНоменклатуры (подчиненный
регистратору, периодичность – «По позиции регистратор»).
Рис. 3.46.
Очевидно, что цены должны храниться в двух разрезах. Первый разрез
это сама номенклатура, а второй разрез – вид цены. Поэтому в регистре у нас
будет два измерения ВидЦены и Номенклатура, соответствующих типов.
Где нам хранить цены, в измерениях или в ресурсе? Если мы будем хранить
цену в измерении, то для одной номенклатуры, для одного вида цен можно
будет завести несколько цен, что не правильно. Поэтому будем хранить цены
в ресурсе. Должна получиться следующая структура.
99
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.47.
Перейдем в документ УстановкаЦенНоменклатуры
возможность
оперативного
проведения,
и
выберем
ЦеныНоменклатуры в качестве регистратора этого документа.
отменим
регистр
Рис. 3.48.
Настроим, в конструкторе движений проведение документа по регистру
сведений.
100
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.49.
В результате, в модуле документа должен получиться следующий код.
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ЦеныНоменклатуры.Записывать = Истина;
Для Каждого ТекСтрокаСписокНоменклатур Из СписокНоменклатур Цикл
Движение = Движения.ЦеныНоменклатуры.Добавить();
Движение.Период = Дата;
Движение.ВидЦены = ВидЦены;
Движение.Номененклатура = ТекСтрокаСписокНоменклатур.Номенклатура;
Движение.Цена = ТекСтрокаСписокНоменклатур.Цена;
КонецЦикла;
КонецПроцедуры
Листинг 3.16.
Теперь цены у нас будут регистрироваться и храниться. Нам осталось
сделать механизм подбора цены при добавлении (изменении)
номенклатуры в документах Приход и Расход. Очевидно, что нужные цены
мы будем получать из регистра сведений ЦеныНоменклатуры. Для этой
цели, я создам общий модуль, в котором напишу функцию поиска нужной
цены. Непосредственно поиск цены будем осуществлять запросом, поэтому
модуль должен работать в серверном контексте, но поскольку функция
общего модуля будет вызываться с формы, то у данного модуля установим
возможность серверного вызова.
101
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.50.
В этом общем модуле напишем экспортную функцию, в которой будем
получать срез последних из регистра сведений ЦеныНоменклатуры на
определенную дату с отбором по виду цены и номенклатуры.
Функция ПолучитьЦенуТовара(ВидЦены, Товар, Дата) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|
ЦеныНомСрезПосл.Цена КАК Цена
|ИЗ
|
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
|
&Дата,
|
ВидЦены = &ВидЦены
|
И Номененклатура = &Номенклатура) КАК
ЦеныНомСрезПосл";
Запрос.УстановитьПараметр("Дата",Дата);
Запрос.УстановитьПараметр("ВидЦены",ВидЦены);
Запрос.УстановитьПараметр("Номенклатура",Товар);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Возврат 0;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Цена;
КонецФункции
Листинг. 3.17.
102
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Нам осталось сделать форму документа Приход (для расхода сделайте
всё тоже самое самостоятельно), в которой будем работать с обработчиком
ПриИзменении поля Номенклатура таблицы СписокТоваров.
Создадим форму.
Рис. 3.51.
На этой форме нас интересует поле таблицы формы СписокТоваров,
которое связанно с реквизитом Номенклатура одноименной табличной
части документа. У этого поля мы будем работать с событием ПриИзменении,
для которого создадим обработчик в клиентском контексте.
103
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.52.
В процедуре обработчике данного события первым делом получим
данные текущей строки (переменная ТекСтр), затем получим значение цены
для номенклатуры в текущей строке, используя описанную ранее функцию
ПолучитьЦенуТовара (вид цены будет передан - Закупочная), и, напоследок,
пересчитаем сумму.
&НаКлиенте
Процедура СписокТоваровНоменклатураПриИзменении(Элемент)
ТекСтр = Элементы.СписокТоваров.ТекущиеДанные;
ВидЦены = ПредопределенноеЗначение("Справочник.ВидыЦен.Закупочная");
ТекСтр.Цена =
ЦеныНоменклатурыСервер.ПолучитьЦенуТовара(ВидЦены,ТекСтр.Номенклатура,
Объект.Дата);
ТекСтр.Сумма = ТекСтр.Цена * ТекСтр.Количество;
КонецПроцедуры
Листинг. 3.18.
Всё! Учет цен мы сделали, проверим, как работает наш механизм.
Создадим документу УстановкаЦен с закупочными
некоторых номенклатур.
104
ценами для
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.53.
Если в документе Приход, мы выберем какой-нибудь из этих товаров, то
цена подставится автоматически.
Рис. 3.54.
105
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Регистрируем продажи
Для окончательной реализации задачи нам необходимо получить
валовую прибыль. Валовая прибыль это выручка минус себестоимость. И
если с себестоимостью у нас все реализовано, то выручка на данный момент
ни как не фиксируется. Займемся этим.
Для этого создадим отдельный регистр накопления Продажи. Кой вид
должен быть у регистра? Очевидно, что продажи могут только
фиксироваться как факт. У нас не может быть, что продажа увеличивается, а
потом уменьшается и получается какой-то остаток. Поэтому этот регистр
будет оборотный.
Рис. 3.55.
В этом регистре будет всего одно измерение – Товар (тип ссылка на
справочник Номенклатура), и три ресурса – Количество, Себестоимость и
Выручка (тип Число(10,2)).
Рис. 3.56.
106
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Регистратор будет документ Расход.
Рис. 3.57.
Доработаем проведение документа Расход.
Сначала мы изменим самый первый запрос в процедуре
ОбработкаПроведения, в котором мы формируем временную таблицу
ДокТЧ. Добавим в эту таблицу группировку по сумме документа, это будет
выручка.
ВЫБРАТЬ
РасходСписокТоваров.Номенклатура КАК Товар,
СУММА(РасходСписокТоваров.Количество) КАК Количество,
СУММА(РасходСписокТоваров.Сумма) КАК Выручка
ПОМЕСТИТЬ ДокТЧ
ИЗ
Документ.Расход.СписокТоваров КАК РасходСписокТоваров
ГДЕ
РасходСписокТоваров.Ссылка = &Ссылка
СГРУППИРОВАТЬ ПО
РасходСписокТоваров.Номенклатура
ИНДЕКСИРОВАТЬ ПО
Товар
;
/////////////////////////////////////////////////////////////////////////////
///
ВЫБРАТЬ
ДокТЧ.Товар КАК Товар,
ДокТЧ.Количество КАК Количество
ИЗ
ДокТЧ КАК ДокТЧ
Листинг. 3.19.
107
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Не забудем, установить в свойство Записывать регистра накопления
Продажи значение Истина.
Движения.Продажи.Записывать = Истина;
Листинг. 3.20.
Изменим текст запроса, для получения партий: будем из временной
таблицы выбирать поле Выручка, также как и к Количеству применим
агрегатную функцию Максимум к этому полю.
ВЫБРАТЬ
ДокТЧ.Товар КАК Товар,
ДокТЧ.Выручка КАК Выручка,
ДокТЧ.Количество КАК Количество,
ЕСТЬNULL(ПартииТоваровОстатки.Партия,
ЗНАЧЕНИЕ(Документ.Приход.ПустаяСсылка)) КАК Партия,
ЕСТЬNULL(ПартииТоваровОстатки.КоличествоОстаток, 0) КАК
КоличествоОстаток,
ЕСТЬNULL(ПартииТоваровОстатки.СуммаОстаток, 0) КАК СуммаОстаток
ИЗ
ДокТЧ КАК ДокТЧ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПартииТоваров.Остатки(
&Период,
Товар В
(ВЫБРАТЬ
вт.Товар
ИЗ
ДокТЧ КАК вт)) КАК ПартииТоваровОстатки
ПО ДокТЧ.Товар = ПартииТоваровОстатки.Товар
УПОРЯДОЧИТЬ ПО
ПартииТоваровОстатки.Партия.Дата
ИТОГИ
МАКСИМУМ(Выручка),
МАКСИМУМ(Количество)
ПО
Товар
Листинг 3.21.
Теперь перейдем к концу процедуры, где мы заполняем регистр
ПартииТоваров, и будем накапливать себестоимость.
Себестоимость = 0 ;
Пока ВыборкаПартия.Следующий() Цикл
//проверим осталось ли что на списывание
Если Списывать <= 0 Тогда
Прервать;
КонецЕсли;
//подсчитываем партии.
//...//
//делаем движения по документу
Движение = Движения.ПартииТоваров.Добавить();
108
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
//...//
Списывать = Списывать - СписыватьПартию;
Себестоимость = Себестоимость + СуммаПартии;
КонецЦикла;
Листинг 3.22.
Теперь мы будем знать общую себестоимость товара по всем партиям.
Осталось только заполнить регистр Продажи.
Продажи = Движения.Продажи.Добавить();
Продажи.Товар = ВыборкаТовар.Товар;
Продажи.Себестоимость = Себестоимость;
Продажи.Количество = ВыборкаТовар.Количество;
Продажи.Выручка = ВыборкаТовар.Выручка;
Продажи.Период = Дата;
Листинг 3.23.
Всё! Проведение документа Расход доработано. Проверим, как
заполняется регистр: перепроведем документы расхода.
Рис. 3.58.
109
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Отчет «Валовая прибыль и себестоимость»
Создадим отчет, который будет показывать выручку, себестоимость и
валовую прибыль проданного товара.
Сделаем новый объект отчет, который назовем «Валовая прибыль».
Рис. 3.59.
Создадим схему компоновки данных, а в нем добавим набор данных
Запрос.
Рис. 3.60.
У созданного набора данных создадим запрос, в котором выберем
виртуальную таблицу Обороты регистра накопления Продажи. У этой
таблицы выберем все поля.
110
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.61.
Сохраним запрос и исправим заголовки у полей.
Рис. 3.62.
Перейдем на закладку «Вычисляемые поля» и создадим поле
ВаловаяПрибыль, как разница между выручкой и себестоимостью.
111
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.63.
Добавим поля Количество, Себестоимость, Выручка и ВаловаяПрибыль в
ресурсы.
Рис. 3.64.
Вместо параметров НачалоПериода и КонецПериода создадим
параметр Период (тип СтандартныйПериод), установим для этих двух
параметров выражения, и сделаем ограничение доступности.
Рис. 3.65.
В настройках создадим группировку детальных записей со всеми
выбранными полями.
112
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.66.
А также, установим параметру Период пользовательскую доступность.
Рис. 3.67.
Посмотрим, как работает наш отчет.
113
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 3.68.
Теперь мы можем видеть результат работы предприятия за какой-либо
период.
Задания для самостоятельной работы
1)
2)
3)
4)
Реализуйте учет продаж в конфигурации, где ведется расчет
себестоимости по среднему, также в этой конфигурации сделайте отчет
по валовой прибыли;
Разработайте отчет, в котором будут выводиться остатки товаров на
складах. Учтите, что в отчете должна быть информация о
количественном и суммовом остатке;
В документе Расход создайте два реквизита Контрагент и Менеджер
(сделайте для них соответствующие справочники). Продажи учитывайте
в разрезе контрагентов и менеджеров. Отчет по валовой прибыли
доработайте так, чтобы можно было посмотреть продажи с
группировкой по контрагенту, а менеджер был в детальных записях;
Разработайте конфигурацию, где будет вестись партионный учет, только
в качестве партии будет документ ЗаказПокупателя (создайте
самостоятельно), который будет указываться в табличной части
документа Расход.
114
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Глава 4. Блокировка данных при решении задач оперативного
учета
Понятие транзакции
Прежде чем начнем разбирать блокировки, зачем они нужны и их
применение в задачах оперативного учета (в других задачах они тоже
применяются, но в задачах оперативного учета они нужны наиболее остро),
изучим такое понятие как транзакция.
Транзакция - это цепочка действий в базе данных, которые ведут к
целостному изменению данных в базе. Транзакция или может быть
выполнена полностью, тогда будет произведено целостное изменение
данных в базе, или может быть не выполнена совсем, тогда данные в базе
останутся неизменны. Транзакция не может быть выполнена частично, когда
часть данных в базе изменена, а часть – нет. Любая база 1С работает с СУБД
(системой управления баз данных), если это файловая база, то работу СУБД
эмулирует платформа 1С, если мы имеем клиент-серверный вариант
хранения данных, то это сторонняя СУБД (Microsoft SQL Server, PostgreSQL и
т.п.). Поэтому в понятиях 1С транзакция несет тот же самый смысл, как и в
понятиях СУБД – фиксация и изменение каких-то данных в базе.
Транзакция может быть выполнена неявно, например, когда
пользователь интерактивно записал какой-то элемент справочника или,
когда в коде выполнился метод Записать() какого-либо объекта, а может
быть описана разработчиком – выполнена явно. Для явного выполнения
транзакций в языке разработки платформы 1С 8.3 имеются следующие
методы:



НачатьТранзакцию() - метод открывает транзакцию, все изменения
после этого оператора будут или полностью записаны, или полностью
отменены;
ЗафиксироватьТранзакцию() – метод закрывает транзакцию, все
изменения, внесенные в базу данных будут успешно сохранены;
ОтменитьТранзакцию() – метод отменяет транзакцию, все изменения,
внесенные в базу данных не будут сохранены.
115
Низамутдинов Ильяс

ТранзакцияАктивна()
открыта.
Разработка оперативного учёта в 1С 8.3
- метод возвращает Истина если транзакция
Методы НачатьТранзакцию() - ЗафиксироватьТранзакцию() или
ОтменитьТранзакцию() должны использоваться в связке. То есть, если мы
где-то начали явную транзакцию, то должны ее или зафиксировать или
отменить. Если транзакция начата явно, но не зафиксирована, то она
автоматически будет отменена.
Сформулируем правило: код, который начинал транзакцию, должен ее
или закончить или отменить. Очень важно, чтобы транзакция выполнялась
внутри одного метода, нельзя начать транзакцию в одной процедуре, а
зафиксировать или отменить в другой.
Обращаю внимание, что в случае простой программной записи объекта,
нет смысла использовать явное выполнение транзакции. Например, в этом
случае:
НоваяНоменклатура = Справочники.Номенклатура.СоздатьЭлемент();
//заполняем
НоваяНоменклатура.Записать();
Листинг 4.1.
Использование
конструкции
НачатьТранзакцию
–
ЗафиксироватьТранзакцию будет излишним, поскольку метод Записать()
автоматически открывает и закрывает транзакцию.
Если же у нас происходит какое-то чтение данных из базы, или
одновременная запись двух связанных объектов, то необходимо
использовать явное выполнение транзакции.
Мы переходим к важному моменту, что транзакции в 1С могут быть
разной степени вложенности: внутри одной транзакции может начаться
другая транзакция и т.п. (причем, вложенными могут быть и неявные
транзакции).
Но в тоже время 1С не поддерживает вложенность
транзакций. Это значит, что если у нас транзакция внутри отменена, то и
верхняя транзакция так же будет отменена.
Разберем вложенность транзакций на примерах.
116
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
НачатьТранзакцию();
//получаем как-то объект1
Объект1.Записать();
НачатьТранзакцию();
//получаем как-то объект2
Объект2.Записать();
ЗафиксироватьТранзакцию();
Листинг 4.2.
При такой конструкции, оба объекта не будут записаны в базу.
Поскольку мы начали транзакцию верхнего уровня, потом начали
транзакцию нижнего уровня, а потом зафиксировали транзакцию нижнего
уровня, при этом транзакция верхнего уровне не была зафиксирована, она
автоматически завершилась откатом.
НачатьТранзакцию();
//получаем как-то объект1
Объект1.Записать();
НачатьТранзакцию();
//получаем как-то объект2
Объект2.Записать();
ОтменитьТранзакцию();
ЗафиксироватьТранзакцию();
Листинг 4.3.
В этом случае ни один объект не запишется в базу! Потому что
внутренняя транзакция отменена, и, как следствие, внешняя транзакция
также откатилась. Запомните этот пример! Он очень примечателен,
поскольку при конструкции такого вида:
НачатьТранзакцию();
Попытка
//получаем как-то объект1
Объект1.Записать();
Исключение
//что-то сообщаем
КонецПопытки
Попытка
//получаем как-то объект2
Объект2.Записать();
Исключение
//что-то сообщаем
КонецПопытки
ЗафиксироватьТранзакцию();
Листинг 4.4.
Потенциально возможны ошибки. Если запись первого или второго
объекта прервется по ошибке, то при попытке зафиксировать транзакцию
117
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
будет выдана ошибка «В данной транзакции уже происходили ошибки».
Потому что, как мы уже знаем, при записи объекта открывается внутренняя
неявная транзакция, которая или фиксируется, если объект был записан
успешно, или откатывается, если возникла ошибка. В случае отката
внутренней транзакции, внешняя транзакция станет также несостоятельной,
поэтому все попытки ее зафиксировать, обречены на неудачу.
Таким образом, можно сделать вывод: в «1С: Предприятие 8.3»
существует только одна транзакция, которая включает в себя все внутренние
транзакции. Эта транзакция работает по принципу «все или ни чего»: чтобы
транзакция нормально завершилась, все её внутренние транзакции должны
быть нормально завершены, чтобы транзакция была отменена, достаточно
отмены хотя бы одной внутренней транзакции.
Рекомендуется явные транзакции применять вместе с операторами
Попытка – Исключение- КонецПопытки. При такой работе необходимо
придерживаться следующих правил:
1)
2)
3)
4)
Начинать транзакцию следует перед оператором Попытка;
Фиксировать транзакцию нужно перед оператором Исключение, чтобы
потом не возникло ни каких исключительных ситуаций.
В блоке исключение первым делом необходимо отменить транзакцию,
а потом проводить остальные действия;
При использовании вложенных транзакций, в блоке исключения
необходимо использовать оператор ВызватьИсключение. Иначе
исключение не будет передано в верхний уровень транзакции, внешняя
транзакция не будет явным образом отменена, произойдет попытка
фиксации внешней транзакции, которая будет уже несостоятельной, что
приведет к ошибке «В данной транзакции уже происходили ошибки».
Связка явных операторов транзакций и операторов исключения должна
иметь такой вид:
118
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
НачатьТранзакцию();
Попытка
//что-то делаем
//заполняем
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
//сообщаем об ошибке
ВызватьИсключение;
КонецПопытки;
Листинг 4.5.
Разберем работу методов транзакций на одной ситуации.
Например, нам где-то в коде необходимо программно изменить
элемент основного справочника и элемент другого справочника, который
подчинен основному.
Как мы это сделаем. Мы сначала получим оба объекта из ссылок, потом
внесем изменения, а потом запишем оба этих объекта. Такой метод вполне
рабочий в простых учебных базах, где работает один человек, где не
запущены какие-то фоновые процессы и т.п.
В реальных же базах могут возникнуть следующие проблемы:
1)
2)
3)
Нужный элемент может изменить в это же время другой пользователь.
Как избежать одновременного изменения несколькими пользователями
одного объекта мы узнаем в следующем разделе.
Во время изменений какого-нибудь из объектов может возникнуть
ошибка, которая приведет к остановке работы всего кода. Хорошо если
этот процесс контролирует пользователь, а если он происходил без его
участия? Например, ночью во время регламентного задания.
Ошибка, возникшая при записи одного из объектов, приведет к отмене
записи объекта, чем может быть нарушена бизнес-логика программы. К
примеру, у нас получилось, что основной объект изменился, а
подчиненный нет, или наоборот.
Рассмотрим пример: пусть у нас происходят события, во время которых
записываются какие-то данные. Тогда все записи объектов правильнее всего
выполнять в попытке.
119
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Попытка
//какие-то события с записью объектов
Исключение
//сообщение о неудавшейся записи
КонецПопытки;
Листинг 4.6.
В данном случае ошибка не повлияет на последовательность
выполнения кода программы, и наша программа не прервет своего
выполнения. Но при такой конструкции, ошибка, которая может возникнуть
при записи одного из объектов, приведет к нарушению целостности данных
в базе и бизнес-логики работы программы.
Поэтому перед тем, как начнем записывать данные в базу, откроем
транзакцию, и закроем её после записи в базу, а в случае ошибки (когда
сработает исключение) отменим транзакцию.
НачатьТранзакцию();
Попытка
//какие-то события с записью объектов
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
//сообщение об неудавшейся записи
ВызватьИсключение;
КонецПопытки;
Листинг 4.7.
Разберем пример корректного использования вложенных транзакций.
Этот пример будет носить больше академический характер, призванный
показать «как правильно». В прошлых главах мы создали справочник
Склады, сейчас сделаем справочник Помещения, который будет подчинен
справочнику Склады. А также добавим справочнику Склады реквизит
Оптовый (тип булево).
Рис 4.1.
120
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
При записи элемента справочника Склады будем проверять, есть ли у
этого элемента уже помещения, и если нет, то создадим помещение с
названием «Основное». В модуле объекта справочника Склады необходимо
создать обработчик события ПриЗаписи, в котором будет следующий код.
Процедура ПриЗаписи(Отказ)
НачатьТранзакцию();
Попытка
//для того, чтобы гарантировать, что владелец не изменится во время
записи
//необходимо выполнить блокировку справочника,
//блокировки разберем в следующем разделе
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
|
Помещения.Ссылка КАК Ссылка
|ИЗ
|
Справочник.Помещения КАК Помещения
|ГДЕ
|
Помещения.Владелец = &Владелец";
Запрос.УстановитьПараметр("Владелец",Ссылка);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() тогда
ЗафиксироватьТранзакцию();
Возврат;
КонецЕсли;
НовоеПомещение = Справочники.Помещения.СоздатьЭлемент();
НовоеПомещение.Наименование = "Основное";
НовоеПомещение.Владелец = Ссылка;
НовоеПомещение.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Не удалось записать помещение для склада " + Наименование);
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
Листинг 4.8.
Следующим шагом создадим внешнюю обработку, на форме которой
будет команда, создающая элемент справочника Склады. Для этого на
форме сделаем реквизиты НазваниеСклада (тип строка) и Оптовый (тип
булево), а также команду «Создать склад».
121
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.2.
В обработчике команды напишем код, в котором будем создавать
склад.
&НаСервере
Процедура СоздатьСкладНаСервере()
НачатьТранзакцию();
Попытка
НовСклад = Справочники.Склады.СоздатьЭлемент();
НовСклад.Наименование = НазваниеСклада;
НовСклад.Оптовый = Оптовый;
НовСклад.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Сообщить("Не удалось записать склад " + НазваниеСклада);
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Процедура СоздатьСклад(Команда)
СоздатьСкладНаСервере();
КонецПроцедуры
Листинг 4.9.
Если при записи помещения произойдет ошибка, то и склад в обработке
не запишется. С эмулируем эту ситуацию для наглядности. Для этого в
модуле объекта справочника Помещения искусственно вызовем
исключение: если справочник владелец помещения Оптовый, то будем
выполнять деление на 0.
122
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Процедура ДелениеЧисел(А,Б)
С = А/Б;
КонецПроцедуры
Процедура ПриЗаписи(Отказ)
Если Владелец.Оптовый Тогда
ДелениеЧисел(10,0);
КонецЕсли;
КонецПроцедуры
Листинг 4.10.
Теперь при создании оптового склада обработкой, не будут созданы
помещения для этого склада, а также не будет создан сам склад.
Рис. 4.3.
Зачем нужна блокировка данных?
В предыдущей главе мы с вами сделали простую конфигурацию, в
которой осуществляли суммовой (партионный) учет товаров. И если с этой
конфигурацией будет работать один человек, то ни каких проблем не
должно возникнуть.
Но при наличии нескольких пользователей в
программе (многопользовательском режиме работы) возможны следующие
ситуации:
1)
Проблема потерянного изменения. При одномоментном изменении
данных, часть информации может быть потеряна. Первый пользователь
начал изменять какой-то объект, пусть это будет элемент справочника,
второй пользователь чуть позже также начал изменять этот элемент.
Если первый пользователь зафиксирует изменения раньше второго, то
изменения второго будут утеряны;
123
Низамутдинов Ильяс
2)
Разработка оперативного учёта в 1С 8.3
Проблема грязного чтения. Мы можем прочитать какие-то данные и на
основании чтения этих данных сделать какие-то изменения. Но, если до
момента принятие изменений изначальные данные будут изменены, то
в дальнейшем могут возникнуть коллизии. Например, у нас на складе
имеется 5 штук товара А. Мы документом Расход1 списываем 4 штуки,
перед этим проверив остатки. Другой пользователь документом
Расход2 почти одновременно списывает 3 штуки товара, но проверка
остатков при проведении этого документа была после того, как
документ Расход1 прочитал информацию об остатках, но до того, как он
записал свои данные в базу. Т.е. при проведении документа Расход2 мы
узнали, что остатка 5 штук товара, и спокойно списали 3 штуки. Таким
образом, у нас в остатках стало минус 2-е штуки товара.
Это не полный перечень возможных проблем, но наиболее
показательный. Т.е. если мы не будем блокировать какой-то объект или
набор данных (например, записи регистра накопления), то у нас в процессе
работы могут возникать различные коллизии, когда два пользователя (или
пользователь и процесс) обратятся к одному набору данных. Причем, чаще
всего, мы узнаем об этих коллизиях не сразу, а спустя какое-то время, когда
уже наступят негативные последствия.
Есть ли смысл заниматься блокировкой данных, если Вы в конфигурации
работаете только один, или разрабатываете её только для себя? Мой ответ –
да, есть! Во-первых, ваш бизнес может быть масштабирован, и в
дальнейшем у Вас могут появиться сотрудники, которые также станут
пользователями Вашей программы. Во-вторых, Вы можете сделать такую
хорошую программу, что её захочет кто-то у Вас купить, а у них потенциально
может быть больше одного пользователя. В-третьих, вполне возможно, что
Вы захотите часть каких-то процессов автоматизировать, и какие-то объекты
будут создаваться автоматически регламентным или фоновым заданием, в
этом случае, также возможны коллизии.
Разберем, какие
платформа 1С 8.3.
варианты
блокировок
124
данных
предоставляет
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Виды блокировок данных
Механизмы блокировок, которые применяются в платформе 1С можно
разделить на два вида. Это объектные блокировки и транзакционные
блокировки. Дадим определения обоим видам блокировок.
Объектные блокировки – блокировка данных на самом верхнем уровне.
Верхний уровень это работа пользователей с документами, справочниками и
другими объектами на уровне форм. Чтобы при интерактивном
редактировании, создании, удалении и других действий с объектами не
возникали ситуации, когда два пользователя пытаются одновременно
получить доступ к одному объекту, и применяются объектные блокировки.
Транзакционные блокировки - блокировка данных на уровне СУБД. Уровень
СУБД это уровень непосредственного хранения данных. В процессе работы
могут возникнуть ситуации, когда, к примеру, два пользователя пытаются
прочитать один и тот же набор данных, и по полученной информации
сделать какие-либо действия, или когда два пользователя пытаются
одновременно изменить один и тот же набор данных. Чтобы корректно
осуществлялся конкурентный доступ пользователей к данным в СУБД,
необходимо осуществлять транзакционную блокировку этих данных.
Объектные блокировки. Пессимистические и оптимистические
Разберем объектные блокировки. Их в платформе 1С два вида –
пессимистическая и оптимистическая.
Пессимистичная объектная блокировка применяется тогда, когда
пользователь интерактивно редактирует какой-либо объект, чтобы в это
время другой сеанс или этот же сеанс не изменили этот объект. Обычно она
возникает, когда пользователь работает с формой объекта, если в это же
время какой-то другой пользователь попытается изменить этот объект, то
выйдет сообщение «Объект уже заблокирован!».
Продемонстрируем работу пессимистичной блокировки. Для этого
создайте в любой конфигурации, которую делали ранее, роль с полными
правами.
125
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Создадим новую роль.
Рис. 4.4.
Назовем ее «Полные права» и установим все права для этой роли.
Рис. 4.5.
Создадим двух пользователей с полными правами (пред этим обновите
базу данных).
126
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.6.
Рис. 4.7.
127
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.8.
Рис. 4.9.
Запустим теперь два сеанса (нельзя сделать на учебной версии!). Один
под одним пользователем, а другой под другим. Откроем элемент
справочника «Номенклатура» и отредактируем его название, не сохраняя в
базу. Если после этого мы попытаемся сохранить этот же элемент под другим
пользователем, то система нам этого не позволит, и будет выведено
системное сообщение, что объект уже заблокирован.
Рис. 4.10.
128
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Это и есть пессимистическая объектная блокировка.
Если же мы сохраним измененный объект под одним пользователем,
когда он был открыт под вторым, и попытаемся после этого сохранить этот
же объект под вторым пользователем, то получим сообщение от том, что
данные уже изменены, и мы не сможем записать этот объект.
Рис. 4.11.
В этот раз у нас отработала оптимистическая объектная блокировка.
Разработчик может целенаправленно снимать и устанавливать
объектные пессимистические блокировки управляемой формы. Для этого
необходимо
использовать
методы
формы
ЗаблокироватьДанныеФормыДляРедактирования
и
РазблокироватьДанныеФормыДляРедактирования.
Сделаем
простой
пример, создадим форму для элемента справочника Номенклатура.
129
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.12.
На форме создадим две команды «Заблокировать» и «Разблокировать»,
которые разместим в командной панели.
Рис. 4.13.
Создадим для каждой команды обработчики, и в этих обработчиках
команды напишем следующий код.
130
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.14.
&НаКлиенте
Процедура Заблокировать(Команда)
ЭтаФорма.ЗаблокироватьДанныеФормыДляРедактирования();
КонецПроцедуры
&НаКлиенте
Процедура Разблокировать(Команда)
ЭтаФорма.РазблокироватьДанныеФормыДляРедактирования();
КонецПроцедуры
Листинг 4.11.
Проверьте сами работу этих методов. Обратите внимание, как при этом
поведут себе оптимистические блокировки.
Я не буду глубоко вдаваться в механизмы работы объектных
группировок, поскольку при решениях задач оперативного учета в основном
используются транзакционные блокировки.
Транзакционные блокировки. Автоматические и управляемые
Перейдем к транзакционным блокировкам, к тем блокировкам, которые
действуют непосредственно на информацию в базе данных. Мы уже знаем,
что в масштабируемой конфигурации должна осуществляться параллельная
работа пользователей, но при параллельной работе могут возникать
коллизии, когда два или больше пользователей в один и тот же момент
времени могут получить доступ к одному набору данных. Без значения,
нужен ли им набор данных для чтения и последующего изменения, или
131
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
просто для изменения. Проблема есть и ее нужно решать. Для ее решения в
платформе 1С 8 возможно внедрять транзакционные блокировки, т.е.
блокировки, которые будут действовать на транзакции: мы не сможем
прочитать какие-то данные, пока не будет выполнена транзакция, которая их
заблокировала, или мы не сможем изменить какие-то данные, пока они не
будут освобождены заблокировавшей их транзакцией.
Если объектные блокировки были на верхнем уровне, на уровне работы
пользователя, то транзакционные блокировки уже осуществляются на
нижнем уровне. На уровне СУБД.
Транзакционные блокировки бывают двух видов автоматические и
управляемые.
Если в конфигурации применяется режим автоматических блокировок,
то СУБД будет использовать собственный менеджер блокировок, тем самым
разработчику нет необходимости дополнительно думать об установке
блокировки на ту или иную транзакцию - все блокировки будут отданы на
управление СУБД.
Если же конфигурация работает с режимом управляемых блокировок, то
разработчик может сам устанавливать блокировки при записи (чтении)
данных при помощи менеджера блокировок платформы 1С, что позволяет
более тонко настроить параллельную работу пользователей. Во всех
современных конфигурациях применяется режим управляемых блокировок,
также фирма 1С рекомендует использовать этот режим при разработке
новых конфигураций, поскольку он позволяет существенно повысить
параллельность работы.
Режим блокировок задается в свойстве конфигурации, которое
называется «Режим управления блокировкой данных».
Посмотрим свойство «Режим управления блокировкой данных» в какойнибудь нашей конфигурации, разработанной в предыдущей главе. Для этого
выделим корень конфигурации, вызовем контекстное меню и выполним в
нем команду «Свойства».
132
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 4.15.
В палитре свойств нас интересует свойство «Режим управления
блокировкой данных» на закладке «Совместимость».
Рис. 4.16.
133
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
У этого свойства имеется три значения «Автоматический»,
«Управляемый» и «Автоматический и управляемый». В том случае, если в
свойство установлено значение «Автоматический», то при записи объекта
будет задействован менеджер блокировок СУБД. Если в свойство
установлено значение «Управляемый», то при записи объектов используется
менеджер блокировок платформы 1С. Если же стоит значение
«Автоматический и управляемый», то в свойствах объекта можно
определить, какой менеджер блокировок будет использоваться при записи
этого объекта.
Если мы зайдем в палитру свойств любого объекта, то в свойстве
«Режим управления блокировок» мы можем установить, какой менеджер
блокировок (СУБД или платформы) используется при работе с этим
объектом.
Рис. 4.17.
134
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Данное поле есть смысл настраивать, когда в свойстве конфигурации
«Режим управления блокировкой данных» установлено значение
«Автоматический и управляемый», в остальных случаях нет смысла его
изменять!
Мы разберем работу с управляемыми блокировками в платформе 1С
8.3.
Управляемые блокировки устанавливаются при помощи специального
объекта встроенного языка программирования – БлокировкаДанных. При
помощи этого объекта осуществляется явная блокировка данных от чтения
или изменения другими сессиями программы 1С. Создается он при помощи
конструктора Новый.
Блокировка = Новый БлокировкаДанных;
Листинг 4.12.
Обращаю Ваше внимание, с объектом БлокировкаДанных нельзя работать
в контексте тонкого клиента и веб-клиента! Его можно использовать
или в серверном контексте, или в контексте толстого клиента.
Для того, чтобы понять, как работает этот объект доработаем пример из
раздела «Понятие транзакции», где мы при записи элемента справочника
Склады создавали помещение в том случае, если у него еще нет помещений
(см. листинг 4.8, стр. 121). Поскольку наша задача состоит в том, чтобы
помещение было создано только в том случае, если у склада нет ни одного
помещения, то очень важно, чтобы во время наших действий ни кто не успел
создать новое помещение, у которого владельцем будет этот склад. Для
этого в самом начале транзакции, нам нужно установить блокировку тех
элементов справочника Помещения, у которых владельцем является
записываемый склад. Пусть даже таких элементов еще и не создано. Для
этого мы будем использовать объект БлокировкаДанных.
БлокировкаДанных это коллекция, состоящая из элементов блокировки.
В каждом элементе блокировки указывается пространство блокировок,
которая определяет, какая область данных будет заблокирована.
Пространства блокировок совпадают с объектами метаданных. Для того
чтобы добавить новый элемент коллекции блокировки данных, необходимо
135
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
использовать метод Добавить, где в качестве параметра в виде строки
указывается имя пространства блокировки.
ЭлементБлокировки = Блокировка.Добавить("<ИмяПространстваБлокировки>");
Листинг 4.13.
Имена пространств блокировок задаются следующим образом. Для
констант, справочников, документов, планов видов характеристик, задач,
бизнес-процессов и остальных объектов кроме регистров:
Константа.<ИмяКонстанты>
Справочник.<ИмяСправочника>
Документ.<ИмяДокумента> и т.д.
Для регистров сведений, накопления, бухгалтерии и расчетов:
РегистрСведений.<ИмяРегистра>
РегистрСведений.НаборЗаписей.<ИмяРегистра> (если есть регистратор)
РегистрНакопления.<ИмяРегистра>
РегистрНакопления.НаборЗаписей.<ИмяРегистра>
РегистрБухгалтерии.<ИмяРегистра>
РегистрБухгалтерии.НаборЗаписей.<ИмяРегистра>
РегистрРасчетов.<ИмяРегистра>
РегистрРасчетов.НаборЗаписей.<ИмяРегистра>
Для объектных данных существует только одно такое пространство
блокировок – это сам объект. А для необъектных данных (регистр сведений,
накопления и т.д.) определено два пространства блокировок сам регистр и
набор записей регистра. В том случае, когда мы работаем с самим регистром
(например, получаем остатки по регистру накопления или срез последних по
регистру сведений), то нужно использовать пространство блокировки для
этого
регистра
(РегистрНакопления.<ИмяРегистра>
или
РегистрСведений.<ИмяРегистра>). А когда мы работаем с записями регистра
(добавляем, удаляем, редактируем), то нужно использовать пространство
136
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
блокировок
для
набора
записей
(РегистрНакопления.НаборЗаписей.<ИмяРегистра>).
регистра
Вернемся к нашей задаче. Нам необходимо заблокировать справочник
Помещения. Поэтому после начала транзакции в коде листинга 4.8 (стр. 121)
создадим объект БлокировкаДанных, создадим новый элемент этого
объекта, в котором укажем пространство блокировки справочник
Помещения.
НачатьТранзакцию();
Попытка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Справочник.Помещения");
//....продолжение кода листнига 4.3
Листинг 4.14.
Если мы так и оставим, то будет заблокирован весь справочник.
Естественно, нам этого делать не нужно, нам нужно заблокировать только те
элементы справочника, у которых владелец это ссылка на наш
записываемый склад. Для этого нам нужно установить условие на поля
пространств блокировки данных. Установить условие можно двумя
способами:
1)
2)
При помощи указания поля и значения, по которому нужно отобрать
нужные поля;
При помощи источника данных (например, таблицы значений). В этом
источнике данных может содержаться перечень некоторых данных, по
которым установятся условия на поля пространств блокировки данных.
Сейчас мы разберем установки условий при помощи указания полей и
значений, а ниже рассмотрим использование источника данных.
Делается это при помощи метода элемента коллекции блокировки
данных УстановитьЗначение, где в качестве первого параметра указывается
название поля, по которому нужно осуществить блокировку, а в качестве
второго параметра блокируемое значение. В нашем случае, это будет
следующий код:
137
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
//...начало кода листнига 4.3
ЭлементБлокировки = Блокировка.Добавить("Справочник.Помещения");
ЭлементБлокировки.УстановитьЗначение("Владелец",Ссылка);
//....продолжение кода листнига 4.3
Листинг 4.15.
В методе УстановитьЗначение мы указали поле Владелец и ссылку на
склад, таким образом мы установим блокировки на все элементы
справочника Помещения, у которых владелец наш записываемый склад.
Но…Чтобы установить блокировку по любым полям объекта (кроме поля
Ссылка) нам нужно указать эти поля в свойстве объекта «Поля блокировки
данных», иначе произойдет исключительная ситуация.
Найдем у справочника Помещения это свойство и добавим в нем поле
Владелец.
Рис. 4.18.
Нам осталось установить режим блокировки и непосредственно
заблокировать пространство.
Режим блокировки данных задается при помощи системного
перечисления РежимБлокировкиДанных. У этого перечисления всего два
значения – Исключительный и Разделяемый.
138
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Если у нас установлен режим Исключительный, то другие транзакции не
смогут даже прочитать эти данные. Если же установлен режим Разделяемый,
то другие транзакции смогут прочитать эти данные, но не смогут их
изменить.
Мы будем применять исключительный режим блокировки данных. Для
этого в свойство Режим элемента блокировки запишем нужное значение
перечисления. После установки режима нам останется только заблокировать
пространство. Делается это при помощи метода Заблокировать объекта
БлокировкаДанных.
В конечном итоге, у нас должен получиться следующий код блокировки.
//...начало кода листнига 4.3
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("Справочник.Помещения");
ЭлементБлокировки.УстановитьЗначение("Владелец",Ссылка);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
//....продолжение кода листнига 4.3
Листинг 4.16.
И всё! Сейчас, если мы будем сохранять, какой-нибудь созданный ранее
склад, поставим точку останова после блокировки, а потом откроем «1С:
Предприятие» под другим пользователем (новый сеанс) и попытаемся
создать помещение для этого же склада, то записать нам новое помещение
платформа не позволит.
Рис. 4.19.
139
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Если Вы повторите это на своей базе, то заметите, что ошибка возникла
не сразу, программа «задумалась» на какое-то время. Это время называется
«Время ожидания блокировки данных», и устанавливается в параметрах
информационной базы.
Рис. 4.20.
Рис. 4.21.
Перейдем к вопросам блокировок при решении задач оперативного
учета. Для этого мы будем использовать конфигурацию, где осуществляли
расчет себестоимости по среднему значению.
Напомню, каким образом осуществлялось проведение документом
Расход по регистрам накопления: сначала мы делали движения по регистру
ОстаткиТоваров, потом осуществляли контроль над остатками в регистре с
учетом уже свершившегося движения (по «новой методике»), и если
140
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
остатков хватало, то делали движения по регистру Себестоимость,
списывая товары по определенному алгоритму.
Блокировку необходимо накладывать на регистр ОстаткиТоваров,
причем, поскольку мы делаем проведение по «новой методике», т.е.
сначала записываем регистр, а потом уже проверяем остатки, то нет смысла
использовать объект БлокировкаДанных, который мы ранее изучали. Для
этого можно применить свойств набора записей регистра накопления
БлокироватьДляИзменения! При установке значения Истина в это свойство,
в регистре накопления устанавливается управляемая блокировка по всем
комбинациям измерений, по которым осуществлялась запись. К примеру,
если у нас делается запись по складу «Основной», то все поля регистра
накопления, где присутствует этот склад, будут заблокированы.
Свойство БлокироватьДляИзменения
набора записей регистра
накопления можно использовать только в том случае, когда свойству
конфигурации «Режим управления блокировок» установлено значение
«Управляемый»!
Имейте в виду, блокировка установится только после записи регистра.
Поэтому при применении «старой методики» контроля остатков нет смысла
использовать это свойство.
В модуле документа Расход изменим код в процедуре
ОбработкаПроведения, где будем осуществлять блокировку регистра перед
записью.
//делаем движения по регистру накопления ОстаткиТоваров
Движения.ОстаткиТоваров.БлокироватьДляИзменения = Истина;
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.ОстаткиТоваров.Записать();
//контроль остатков в регистре накопления ОстаткиТоваров
Листинг 4.17.
На этом, в принципе, можно закончить. Нет смысла в дальнейшей
блокировке регистра накопления Себестоимость, так как в нашей
конфигурации регистры накопления ОстаткиТоваров и Себестоимость
«работают в связке». Сначала делается движение по регистру
ОстаткиТоваров, а потом по регистру Себестоимость, и если у нас регистр
141
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
остатков будет заблокирован, то мы не сможем сделать движения и по
регистру Себестоимости. Поэтому такая блокировка будет излишней. Но, мы
ее все равно сделаем. Во-первых, в академических целях, чтобы научиться
применять объект БлокировкаДанных при работе с регистрами накопления.
Во-вторых, при сдаче экзамена на «1С: Специалист по платформе «1С:
Предприятие 8» экзаменаторы обращают внимание на блокировку регистра
себестоимости.
Напомню, что при проведении документа Расход, мы сначала получали
данные запросом из регистра Себестоимость, а потом уже по
определенному алгоритму делали движения по этому регистру. Поскольку
наша задача получить актуальные итоги, то нам нужно заблокировать
таблицу регистра как можно раньше, т.е. до того момента, как мы выполнили
запрос.
Я рекомендую это делать между кодом с текстом запроса и кодом, где
мы получаем результат запроса (см. листинг 4.13).
Движения.Себестоимость.Записывать = Истина;
Запрос.Текст = "ВЫБРАТЬ
//запрос про регистру накопления Себестоимость
|
ПО ДокТЧ.Товар = СебестоимостьОстатки.Товар";
Запрос.УстановитьПараметр("Период",МоментВремени());
//Здесь будем блокировать регистр накопления Себестоимость
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Листинг 4.18.
В этом месте создадим объект БлокировкаДанных и добавим элемент
коллекции для этого объекта. Поскольку мы будем работать с самим
регистром (получать остатки), то используем пространство блокировки сам
регистр накопления Себестоимость.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Себестоимость");
Листинг 4.19.
У нас не будет осуществляться блокировка по какому-то одному
значению, как мы это делали раньше (см. листинг 4.16 стр. 139). Нам нужно
142
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
осуществить блокировку по целому списку номенклатур, для этого мы
воспользуемся
свойством
ИсточникДанных
элемента
объекта
БлокировкаДанных. В это свойство можно передать таблицу значений,
результат запроса и табличную часть. И у нас будут заблокированы все
записи (строки в таблицах базы данных), в полях которых содержаться
перечисленные в источнике значения. Т.е. если у нас в табличной части три
номенклатуры, то все записи с этой номенклатурой будут заблокированы.
Передадим в источник блокировки табличную часть документа Расход.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Себестоимость");
ЭлементБлокировки.ИсточникДанных = СписокТоваров;
Листинг 4.20.
Но этого пока мало. Нам нужно указать какое поле из источника
связанно с полем в пространстве блокировки. Для этого нужно использовать
метод
ИспользоватьИзИсточникаДанных
элемента
объекта
БлокировкаДанных. Этот метод имеет следующий синтаксис.
ИспользоватьИзИсточникаДанных(<ПолеПространстваБлокировок>,
<ПолеИсточника>).
Где
ПолеПространстваБлокировок – поле в пространстве блокировок, которое
нужно будет заблокировать. В нашем случае это название измерения
регистра накопления («Товар»).
ПолеИсточника – поле из источника, с которого будут отобраны данные, по
которым осуществится блокировка. В нашем случае это название реквизита
из табличной части документа («Номенклатура»).
Продолжим наш код.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Себестоимость");
ЭлементБлокировки.ИсточникДанных = СписокТоваров;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Товар","Номенклатура");
Листинг 4.21.
143
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Нам
осталось
установить
режим
блокировки
(он
будет
Исключительный, чтобы ни кто не смог даже прочитать данные), и
заблокировать регистр накопления.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.Себестоимость");
ЭлементБлокировки.ИсточникДанных = СписокТоваров;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Товар","Номенклатура");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Листинг 4.22.
Источник данных можно использовать совместно с установкой
значений. Например, если мы решим вручную заблокировать регистр
ОстаткиТоваров, не используя свойство БлокироватьДляИзменения набора
записей регистра накопления, то конструкция блокировки данных будет
иметь такой вид.
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
ЭлементБлокировки.ИсточникДанных = СписокТоваров;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Товар","Номенклатура");
ЭлементБлокировки.УстановитьЗначение("Склад",Склад);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
Листинг 4.23.
Где:
СписокТоваров – табличная часть документа Расход, а Склад – реквизит.
Естественно, в этом случае не нужно дополнительно устанавливать свойство
БлокироватьДляИзменения, это будут излишние действия.
Такой вариант блокировки остатков осуществим,
использовать старую методику проверки остатков.
144
если
Вы
будете
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Задания для самостоятельной работы
1)
2)
3)
Добавьте блокировки регистров накопления в конфигурации, где
происходит списание по партиям. Для тренировки осуществляйте
блокировки всех регистров. Напишите, почему блокировка по регистру
накопления ПартииТоваров избыточная;
В главе второй в заданиях для самостоятельной работы мы создали
конфигурацию, где использовали контроль остаток по старой методике.
Добавьте блокировки в эту конфигурацию;
В главе второй в заданиях для самостоятельной работы мы доработали
конфигурацию, введя регистр накопления ОстатокДенежныхСредств.
Разработайте систему блокировок для работы с этим регистром
накопления.
145
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Глава 5. Работа с последовательностями
Общие сведения
В прошлых главах мы с вами разработали конфигурации, осуществили
количественный и суммовой (партионный) оперативный учет. Вся суть нашей
работы в том, что были разработаны документы, которые делали движения
по регистрам накопления. Эти движения или увеличивали остатки товаров,
или уменьшали их. И если работа с нашими данными будет вестись в
хронологическом порядке: все документы будут вводиться последовательно
по времени, то ни каких проблем быть не должно. Но, если пользователи
начнут создавать документы прошлой датой, то очень вероятны различные
ошибки и коллизии.
Приведем, простой пример, пусть у нас товар А поступил на склад 1-го
числа в количестве 3-х штук, и 3-го числа в количестве 2-х штук.
Впоследствии, он был списан 5-го числа в количестве 4-х штук. И у нас
остался остаток 1 штука (см. рис. 5.1).
Рис. 5.1.
Если же пользователь 2-го числа создаст документ на списание товара А
в количестве 2 штук, то платформа даст его провести. Ведь на этот момент по
данным базы остаток будет 3 штуки. Почему бы и нет. И после этих действий
по регистру накопления у нас будет остаток товара А минус одна штука (см.
рис. 5.2).
146
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.2.
Согласитесь, не очень-то хорошая ситуация. Для предотвращения
подобных
проблем
в
платформе
1С
8
имеется
механизм
последовательностей, который реализуется посредством
объекта
метаданных последовательность.
В чем суть этого механизма?
Механизм последовательностей обеспечивает следующее: если
документ при проведении ориентируется на какие-то данные, и эти данные
теоретически могут быть изменены пользователем уже после проведения
этого документа, и если же после проведения документа эти данные по
каким-то причинам изменяются, то этот документ должен быть
перепроведен.
Если кратко: механизм последовательностей обеспечивает правильную
последовательность проведения документов.
Правильная последовательность проведения документов это значит, что
все документы проведены в хронологически верном порядке – проведены
друг за другом на временном интервале.
Несколько примеров. Если мы во время проведения документов цены
на товар берем из периодического регистра сведений (именно во время
проведения, т.е. алгоритм подбора цены отрабатывается в процедуре
ОбработкаПроведения), то при изменении цены товара прошлой датой, все
документы с этого числа должны быть перепроведены. Или, если при
проведении документа мы ориентируемся на остатки товаров, и при
отрицательном остатке не проводим документ, то при изменении остатка в
какой-то момент все документы после этого момента должны быть
147
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
перепроведены. Пример для партионного учета: при изменении входящей
стоимости партии (как вариант, изменили сумму на товар в документе
поступления), необходимо заново провести списание партий, поскольку
себестоимость может измениться.
Как работает данный механизм? Все очень просто!
1)
При записи документ регистрируется в последовательности, в которой
он состоит. Для системы это означает, что при проведении документа
используются какие-то данные, и от их состояния на момент проведения
зависит, корректно будет проведен документ или нет и будет ли
проведен вообще;
2) После проведения документа платформа отслеживает, в каких
последовательностях данный документ зарегистрирован. После этого
платформа определяет, находится ли документ в правильной
последовательности проведения документов или неправильной. Для
этого
смотрятся
проведенные
документы,
которые
были
зарегистрированы в последовательности ранее этого документа. Если
все ранние документы были зарегистрированы в правильной
последовательности, то значит, и новый документ будет
зарегистрирован в правильной последовательности, а иначе он будет
зарегистрирован в неправильной последовательности и его нужно будет
перепровести вместе с остальными документами из неправильной
последовательности.
3) В том случае если какие-то данные изменяются, то:
I.
Платформа определяет, на какие последовательности документов
эти данные влияют;
II.
Для всех документов, которые зарегистрированы в этих
последовательностях позже момента изменения данных,
устанавливается признак, что они должны быть перепроведены;
III.
Документы до момента изменения данных будут находиться в
правильной последовательности, а документы после момента
изменения – в неправильной последовательности.
IV.
Как следствие, любой документ, проведенный после момента
изменения данных, автоматически попадет в неправильную
последовательность и должен быть перепроведен.
4) По любой последовательности пользователь может получить
информацию о моменте времени, ранее которого документы
проведены в правильной последовательности, а позже которого
документы проведены в неправильной последовательности. С этого
момента времени последовательность необходимо восстановить.
148
Низамутдинов Ильяс
5)
6)
Разработка оперативного учёта в 1С 8.3
Восстановление последовательности это перепроведение всех
проведенных документов, которые в ней зарегистрированы в
хронологическом порядке.
Момент времени, до которого документы проводятся в правильной
последовательности, называется граница последовательности.
Покажем наглядно, как работает механизм последовательностей на
примере из начала этой главы: было два документа прихода и один
документ расхода, поскольку документы были проведены в
хронологическом порядке (друг за другом), то все они выстроились в
правильной последовательности (см. рис 5.3). В этом случае граница
последовательности будет момент времени документа расхода.
Рис. 5.3.
После того, как между двумя приходами был создан и проведен
документ расхода, то ситуация изменилась: первый приход и первый расход
будут в правильной последовательности, а второй приход и второй расход –
в неправильной последовательности, и как следствие возникает
необходимость их перепроведения. Граница последовательности сдвинется это будет момент времени первого расхода.
149
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.4.
При перепроведении второго расхода выяснится, что остатков не хватает
для проведения документа, и пользователь должен будет принять
соответствующие меры (в этом случае необходимо разобраться с первичной
документацией).
Внедряем механизм последовательностей для количественного
учета
Внедрим механизм последовательностей для конфигурации, созданной
во второй главе, где мы реализовывали количественный учет товаров.
Для создания новой последовательности раскроем ветвь Документы
дерева метаданных конфигурации, выделим ветку Последовательности,
вызовем контекстное меню и выполним команду «Добавить».
Рис. 5.5.
150
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
После этих действий, будет создана «пустая» последовательность и
откроется окно редактирования объекта. В этом окне на закладке
«Основные» укажем имя последовательности - ОстаткиТоваров.
Рис. 5.6.
Перейдем в окно редактирования последовательности на закладку
«Использование»,
в
которой
задаются
основные
свойства
последовательности.
Рис. 5.7.
151
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
И первое, которое нас интересует это «Перемещение границы при
проведении». По умолчанию в этом свойстве установлено значение
«Перемещать», это значит, что при изменении данных последовательности,
граница этой последовательности будет перемещаться в ту или иную сторону
автоматически. Оставим значение этого свойства по умолчанию.
Следующее свойство это список документов, которые входят в
последовательность – «Входящие документы». Именно эти документы
необходимо
будет
перепроводить
при
изменении
данных
последовательности. Подумаем, какие документы должны войти в эту
последовательность. Напоминаю что, в последовательность должны войти
только те документы, на проведение которых влияет состав данных этой
последовательности, с составом данных разберемся чуть позже, а пока
определим, что это за документы. В нашей конфигурации всего два
документа – Приход (регистрация прихода товара) и Расход (регистрация
расхода товара) оба документа делают движения по остаткам товаров.
Очевидно, что при регистрации прихода не имеет значение, какой остаток
сейчас на складе, поэтому и при изменении этого остатка нет смысла
перепроводить документы прихода. Поэтому документ Приход не должен
входить в нашу последовательность. А вот при проведении расхода, мы
учитываем остаток товара, и если нет остатка по нужному товару, либо его
недостаточно, то проведение документа не происходит, т.е. состав данных
этой последовательности будет влиять на проведение документа расхода.
Поэтому документ Расход войдет в нашу последовательность.
Добавим документ расход в список свойства «Входящие документы».
152
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.8.
Разберемся с последним свойством закладки «Использование» «Движения, влияющие на последовательность», в этом свойстве необходимо
указать регистры, данные которых должны влиять на проведение
документов, которые входят в эту последовательность. Как Вы помните, при
проведении документа Расход осуществляется контроль остатков по регистру
накопления ОстаткиТоваров, т.е. именно от данных этого регистра и
зависит проведение документа, который входит в последовательность.
Включим этот регистр в список.
153
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.9.
Остановимся пока на этих настройках, обновим конфигурацию и
проверим, как работает наша последовательность.
Обращаю внимание, если Вы создали последовательность, когда в базе
данных уже есть какие-то документы, то они автоматически не попадут
в эту последовательность. Для того, чтобы они попали в
последовательность необходимо их перепровести или самостоятельно,
или при помощи какой-либо обработки.
Создадим документы прихода товара «Хлеб» (будем работать только по
одному складу, со складами разберемся ниже):
№ документа
Дата документа
Количество
1
01.05.19
3
2
04.05.19
4
Таб. 5.1.
154
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.10.
Посмотрим, что собой представляет последовательность. Для этого
откроем стандартную обработку «Проведение документов», используя меню
«Все функции».
Рис. 5.11.
155
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.12.
У этой обработки
последовательностей».
нас
интересует
156
закладка
«Восстановление
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.13.
На этой закладке отображается список всех последовательностей
конфигурации совместно с границами последовательностей.
Вы помните, что граница последовательности это момент времени, до
которого документы проведены в правильной последовательности.
Причем из последней картинки, Вы видите, что граница
последовательности пустая. У внимательного читателя может возникнуть
вопрос: «Почему граница последовательности пустая, если уже создано
несколько документов прихода?». И сразу же может возникнуть ответ на
этот вопрос: «Потому что на границу последовательности влияют только
документы, входящие в последовательность, то есть документы расхода».
Этот ответ будет не совсем точным.
Но, перед тем как получить точный ответ на этот вопрос, выясним, по
какому правилу перемещается граница последовательности вперед и назад.
Перенос границы вперед происходит только в случае проведения
документа, входящего в последовательность, но только в том случае, если
между текущей границей последовательности и проводимым документом
157
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
нет неправильно проведенных документов, то есть тех документов, которые
нужно перепровести.
Перенос границы назад происходит тогда, когда осуществляется
изменения данных, которые влияют на последовательность, то есть
происходит запись наборов регистров, и при этом текущая граница
последовательности была позже момента времени записей регистра.
Перенос границы вперед называют восстановление границы
последовательности, а перенос границы назад – сбивание границы.
Упрощенно, применительно к нашему случаю: восстановить границу
последовательности можно только с помощью документов входящих в нашу
последовательность, а сбить границу последовательности можно с
помощью всех документов, делающих движения по регистру накопления
ОстаткиТоваров.
Поэтому, когда мы создали и провели документы прихода, мы не
сдвинули границу последовательности вперед, так как это делают только
документы расхода, но и назад мы ее не сдвинули, поскольку изначально
она пустая.
Если же мы сейчас сделаем списание 1 штуки товара «Хлеб», то наша
граница последовательности сдвинется вперед на момент времени
документа расхода.
Рис. 5.14.
158
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.15.
Если мы сейчас создадим ещё один документ прихода за второе число
(добавим одну штуку товара «Хлеб»), то граница последовательности
сдвинется назад, поскольку произойдет запись в регистр накопления
ОстаткиТоваров.
Рис. 5.16.
Рис. 5.17.
159
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Но, если мы сейчас создадим еще один документ Расход за шестое
число (также спишем одну штуку товара «Хлеб»), то граница
последовательности останется прежней.
Рис. 5.18.
Рис. 5.19.
Так
произошло,
потому
что
между
текущей
границей
последовательности и моментов времени нового документа расхода уже
имеется документ из неправильной последовательности.
При помощи обработки «Проведение документов» мы можем
восстановить нужную последовательность, нажав на кнопку «Восстановить».
В нашем случае будут перепроведены все документы расхода, начиная с
текущего момента времени.
Рис. 5.20.
160
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Если при восстановлении последовательности во время проведения
документа возникнет ошибка, то дальше граница последовательности
сдвигаться вперед не будет, а остановится на моменте времени последнего
безошибочно проведенного документа. Рассмотрим такой пример: изменим
в первом расходе (за 05.05.2019) количество списания на 8 штук.
Рис. 5.21.
Поскольку перед этим расходом было три поступления на 8 штук товара
(3 + 1 +4), то этим расходом у нас спишется весь имеющийся товар,
естественно граница последовательности будет сбита.
Рис. 5.22.
Если мы попытаемся восстановить последовательность, то в обработке
«Проведение документов» у нас произойдет ошибка восстановления
последовательности, и граница останется прежней.
161
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.23.
Теперь вспомним, что у нас ведется количественный учет в разрезе
складов и подумаем: «А правильно ли проводить все документы подряд,
если остатки контролируются в разрезе складов?». Нет, неправильно! Если
мы хотим, чтобы восстановление последовательности происходило в
разрезе складов, нам необходимо доработать нашу последовательность.
Для предотвращения различных коллизий, я рекомендую удалить все
документы в базе, удалить последовательность ОстаткиТоваров,
обновить базу данных и создать новую последовательность аналогичную
удаленной.
Для того, чтобы последовательность можно было разбить на более
мелкие последовательности в различных разрезах (в нашем случае в разрезе
складов), необходимо создать измерения последовательности. Делается это
на закладке «Данные» окна редактирования последовательности.
У нашей последовательности мы создадим единственное измерение,
которое назовем Склад, и тип которого будет ссылкой на справочник Склады.
162
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.24.
Нам осталось связать измерения последовательности с реквизитом
документа и измерением регистра накопления. Делается это в
соответствующих свойствах.
Рис. 5.25.
163
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.26.
Всё! Теперь наша последовательность готова работать в разрезе
складов. При помощи стандартной обработки, мы не сможем получить
границу последовательности в разрезе того или иного склада, но в
последнем разделе, когда мы будем изучать программную работу
последовательностей, мы обратим внимание на этот момент.
Пытливый читатель спросит: «Почему нельзя сделать измерение
Номенклатура для нашей последовательности?». Теоретически это можно
сделать, но практически я не рекомендую использовать такой шаг, поскольку
это негативно скажется на производительности системы.
Физически, в базе данных, последовательность хранится в виде двух
таблиц – таблица регистраций и таблица границ. В таблице регистраций
хранятся документы, зарегистрированные в последовательности в разрезе
измерений, а в таблице границ – границы последовательности в разрезе
измерений. Если мы добавим измерение Номенклатура, то обе эти
таблицы значительно увеличатся в размерах при большом количестве
номенклатуры
в
документах,
что
отрицательно
скажется
на
производительности системы в целом.
Поэтому при конструировании последовательностей очень внимательно
и осторожно нужно подходить к созданию измерений!
164
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Внедряем механизм последовательностей для партионного учета
Внедрим механизм последовательностей в конфигурацию, где был
реализован партионный учет (конфигурация разработана в третьей главе).
Вспомним, как построена эта конфигурация: у нас есть документы
Приход и Расход, которые делают движения по регистрам накопления
ОстаткиТоваров и ПартииТоваров. Документ Приход увеличивает остатки
на обоих регистрах, и результат его проведения не зависит от данных в обоих
регистрах. Документ Расход делает движения расхода по обоим регистрам, и
результат его проведения зависит от данных как в регистре
ОстаткиТоваров, так и в регистре ПартииТоваров.
Подумаем, какие последовательности нужно создать. Нам нужно
создать две последовательности: при помощи первой будут
контролироваться корректные остатки товаров на складах, а при помощи
второй будем контролировать себестоимость списания партий товаров. Это
должны быть две разные последовательности, поскольку возможны
ситуации, когда изменится остаток, но при этом стоимость товара останется
прежней.
Создадим
последовательность
ОстаткиТоваров,
эта
последовательность будет аналогична последовательности из предыдущего
раздела.
Рис. 5.27.
165
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.28.
Рис. 5.29.
Создадим последовательность ПартииТоваров. Входящий документ
будет также документ Расход (ответьте самостоятельно, почему только
один), а в списке движений, влияющих на последовательность, будет регистр
накопления ПартииТоваров.
Рис. 5.30.
166
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.31.
Есть ли смысл делать измерение Партия у этой последовательности?
Очевидно, что нет. Поскольку, партия — это документ поступления товаров,
то документов может быть очень много при активной работе организации,
как следствие физические таблицы регистрации и таблицы границ (см.
предыдущий раздел) значительно возрастут, что скажется отрицательно на
производительности системы в целом.
Вот и всё! Проверьте самостоятельно работу последовательностей в
конфигурации для количественного учета.
Работа с последовательностями при помощи встроенного языка
программирования
В заключительной части текущей главы, мы разберем некоторые
возможности программной работы с последовательностями документов.
Программная работа с последовательностями осуществляется
посредством менеджера последовательностей. Это коллекция, которая
предназначена для управления последовательностями. При помощи этой
167
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
коллекции можно получить доступ к конкретной последовательности, или
при помощи оператора точка, или при помощи квадратных скобок.
ПослОстатков = Последовательности.ОстаткиТоваров;
ПослПартий
= Последовательности["ПартииТоваров"];
Листинг 5.1.
У менеджера последовательностей имеется единственный метод –
Восстановить(), при помощи этого метода можно восстановить или все
последовательности сразу, или какую-то группу последовательностей.
Этот метод имеет следующий синтаксис:
Восстановить(<МоментВремени>, <Последовательности>)
Где:
МоментВремени – необязательный параметр, момент времени, до которого
нужно будет восстановить последовательность, если не указан, то
последовательность восстановится до последнего документа;
Последовательности – необязательный параметр, таблица значений, в
которой перечислен набор последовательностей для восстановления.
Таблица значений должна иметь две колонки. В первой колонке должны
быть перечислены имена последовательностей, как они заданы в
конфигураторе. Во второй колонке, могут содержаться комбинации
измерений последовательности. Они должны быть в виде таблицы значений,
где название колонки - название нужного измерения, а в соответствующей
строке должны быть указаны значения измерения, по которым произойдет
восстановление последовательности. Если измерений нет, или нужно
восстановить последовательность по всем измерениями, то нужно указать
пустую таблицу значений (без строк и колонок).
Для того, чтобы понять как работает этот метод, решим небольшую
задачу: в предыдущей конфигурации для партионного учёта, где мы сделали
две
последовательности,
создадим
обработку,
которая
будет
168
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
восстанавливать эти последовательности ОстаткиТоваров по конкретному
складу.
Самостоятельно создайте обработку, форму, на форму обработки
поместите команду и реквизит Склад (тип ссылка на справочник Склады).
Рис. 5.32.
В серверном обработчике команды напишем, код в котором будем
восстанавливать последовательность ОстаткиТоваров по конкретному
складу.
&НаСервере
Процедура ВосстановлениеНаСервере()
ТаблицПослед = Новый ТаблицаЗначений;
ТаблицПослед.Колонки.Добавить("Последовательность");
ТаблицПослед.Колонки.Добавить("Комбинации");
ТаблицаКомбинаций = Новый ТаблицаЗначений;
ТаблицаКомбинаций.Колонки.Добавить("Склад");
НовСтрКомб = ТаблицаКомбинаций.Добавить();
НовСтрКомб.Склад = Склад;
НовСтр = ТаблицПослед.Добавить();
НовСтр.Последовательность = "ОстаткиТоваров";
НовСтр.Комбинации = ТаблицаКомбинаций;
Последовательности.Восстановить(,ТаблицПослед);
КонецПроцедуры
&НаКлиенте
Процедура Восстановление(Команда)
ВосстановлениеНаСервере();
КонецПроцедуры
Листинг 5.2.
169
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Проверьте самостоятельно работу этой обработки.
Теперь научимся определять границу для определенного значения
нужного измерения. Для этого воспользуемся методом ПолучитьГраницу
менеджера конкретной последовательности.
Данный метод является функцией, которая возвращает момент
времени, и имеет следующий синтаксис:
ПолучитьГраницу(<Отбор>)
Где
Отбор – необязательный параметр, структура, в которой в качестве ключа
идет название измерения, а в качестве значения – значение измерения. Если
параметр не указан, то возвращается граница по всем значениям измерений.
Доработаем нашу обработку: создадим команду, которая будет
возвращать границу последовательности ОстаткиТоваров по конкретному
складу. В серверном обработчике будет следующий код:
&НаСервере
Процедура ПолучитьГраницуНаСервере()
ОстаткиТоваров = Последовательности.ОстаткиТоваров;
Отбор = Новый Структура("Склад",Склад);
Граница = ОстаткиТоваров.ПолучитьГраницу(Отбор);
Сообщить(Граница);
КонецПроцедуры
Листинг 5.3.
После отработки, команда вернет Вам момент времени по конкретному
значению измерения.
Рис. 5.33.
170
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Рис. 5.34.
И научимся восстанавливать границу по конкретному измерению, но
перед этим будем определять нарушена наша последовательность или нет.
Для этого на форме создадим новую команду,
обработчике этой команды напишем следующий код.
и в серверном
&НаСервере
Процедура ВосстановитьТекущуюНаСервере()
ОстаткиТоваров = Последовательности.ОстаткиТоваров;
Отбор = Новый Структура("Склад",Склад);
Если ОстаткиТоваров.Проверить(,Отбор) Тогда
ОстаткиТоваров.Восстановить(,Отбор);
КонецЕсли;
КонецПроцедуры
Листинг 5.4.
В этом листинге у нас используются два метода менеджера
последовательности – Проверить и Восстановить. Первым метод проверяет
нарушена ли конкретная последовательность, а второй метод –
восстанавливает её. Оба метода имеют два необязательных параметра:
первый параметр - момент времени, до которого проверяется
(восстанавливается) последовательность; второй параметр – структура,
которая устанавливает отбор на измерения, где в качестве ключа структуры
указывается название конкретного измерения, а в качестве значения
структуры – значение для конкретного измерения.
Отбор также
необязательный параметр, если он не указан, то восстановление (или
проверка) будет осуществляться по всем измерениям.
Проверьте работу этих методов самостоятельно
171
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Задания для самостоятельной работы
1)
2)
3)
Во второй главе в задании для самостоятельной работы Вы разработали
систему учета денежных средств, создайте последовательность для
корректной работы данной системы (подумайте сами, нужны ли будут
измерения, а если нужны то создайте обработку, которая будет
восстанавливать последовательности для конкретного значения
измерения);
Внедрите механизм последовательностей в конфигурацию, где
реализуется учет товара по средней себестоимости;
Во всех конфигурациях, где внедрен механизм последовательностей
сделайте документ «Закрытие месяца», который при проведении будет
восстанавливать последовательности. Запрещайте проводить документ,
если хотя бы одна из последовательностей не восстановлена.
172
Низамутдинов Ильяс
Разработка оперативного учёта в 1С 8.3
Заключение
Уважаемый коллега! Только что Вы закончили изучение основных
способов автоматизации оперативного учета в «1С: Предприятие 8.3». Эти
знания Вам помогут в дальнейшем более свободно ориентироваться в
задачах оперативного учета, как в новых задачах, которые перед Вами будут
ставить заказчики, так и в сопровождении уже имеющихся задача.
Я искренне надеюсь, что Вы не просто «прочитали» это пособие, а
решили параллельно вместе со мной все примеры из книги, а также все
домашние задания. Поскольку, чтобы научится программировать нужно
именно программировать, а не просто «читать» те или иные учебники.
Материал этого пособия Вам пригодится также и в том случае, если Вы
надумаете сдавать экзамен на сертификат «1С: Специалист по платформе
«1С:Предприятие 8», поскольку в пособии даются основные принципы
решения задач оперативного учёта. А дальше, Вам нужно только закреплять
полученные знания, решением различных задач оперативного учета,
которые в изобилии имеются в задачнике для этого экзамена.
173
Download