Болт М12 ГОСТ
1
Администрирование базы данных
В меню Администрирование вы найдете следующие пункты:
Ведение списка пользователей |
Редактирование списка пользователей, установка паролей, задание интерфейса и набора прав для каждого пользователя. Список пользователей, работающих с базой данных в данный момент времени можно посмотреть в Мониторе пользователей. |
Сохранить данные |
Сохранение конфигурации и данных в архив (создание резервных копий). В этом режиме определенные файлы упаковываются в zip-архив. Если вы работаете с SQL-версией, то для сохранения данных применяйте пункт "Выгрузить данные". Нажимайте эту кнопку почаще и ваши данные никогда не пропадут полностью. |
Восстановить данные |
Восстановить конфигурацию и данные с резервной копии, созданной в предыдущем режиме. |
Выгрузить данные |
Сохранение конфигурации и данных в архив. В этом режиме вся база данных сохраняется в особый файл "dat", который затем упаковывается в zip-архив. |
Загрузить данные |
Восстановить конфигурацию и данные с резервной копии, созданной в предыдущем режиме. |
Настройка журнала регистрации |
Каждое действие пользователя регистрируется в журнал регистрации. Здесь можно настроить фильтр для этого журнала. Сам журнал регистрации можно посмотреть в Мониторе пользователей. |
Тестирование и исправление ИБ |
Тестирование и исправление информационной базы. Нажимайте эту кнопку почаще для профилактики и для исправления ошибок. |
Кодовая страница таблиц ИБ |
Установка кодовой страницы файлов DBF. |
Распределенная ИБ |
Доступно, если у вас установлена компонента "Управление распределенными базами данных (УРБД)". |
Архитектура системы
Нормативно-справочная информация используется для ведения базы сотрудников, штатного расписания и при работе с документами. Документы хранятся в журналах документов. Некоторые документы (прием, увольнение, перемещение) при проведении изменяют список сотрудников и количество вакансий в штатном расписании. По каждому сотруднику, кроме основных данных, ведется дополнительная информация в справочниках Кадровые данные, Состав семьи и т.д. Все эти данные используются для формирования отчетности и информационного обслуживания других пользователей и отделов.
Атрибуты и методы результата запроса
При обходе группировок результата запроса возможно обращение к следующим атрибутам и методам:
Атрибуты справочников
В качестве обязательных реквизитов каждый справочник имеет Код и Наименование. Код элемента справочника может быть как числовым, так и текстовым. Система 1С:Предприятие предоставляет широкие возможности по работе с кодами элементов справочника: автоматическое присвоение кодов, автоматический контроль уникальности кода и другие.
Помимо кода и наименования, в справочниках системы 1С:Предприятие может храниться любая дополнительная информация об элементе справочника. Для хранения такой информации в справочнике может быть создан список реквизитов. Используя механизм реквизитов справочника, легко организовать, например, картотеку сотрудников. Например, справочник Сотрудники почти наверняка будет иметь атрибуты Должность, Оклад и другие. Фирма 1С предвосхитила программистов и ввела во все справочники два уже заданных атрибута: Код
и Наименование. Действительно, практически любой объект из реальной жизни содержит эти атрибуты. Например, для сотрудников кодом выступает табельный номер, а наименованием -- фамилия, имя, отчество (ФИО).
Бухгалтерские итоги
Работа с основными итогами
При вводе операций 1С:Предприятие поддерживает в актуальном состоянии основные бухгалтерские итоги для быстрого обращения к ним при составлении отчетов и выполнения других задач. Основными итогами называются остатки и обороты по счетам и объектам аналитического учета, а также обороты между счетами за любой рассчитанный период с детализацией до месяца.
Для получения других итогов (с детализацией меньше месяца, с получением оборотов между различными объектами аналитики, а также сложных выборок) требуется выполнение предварительных действий — временного расчета или запроса.
Работа с временными итогами (метод Рассчитать)
Для переключения в режим работы с временными итогами следует выполнить метод Рассчитать. После этого объект позволяет получать остатки и обороты по счетам за произвольный период, заданный при вызове метода Рассчитать.
Работа в режиме запроса (метод ВыполнитьЗапрос)
Для получения большого количества итогов в различных разрезах объект «Бухгалтерские Итоги» переключается в режим работы с запросом. Для переключения в этот режим вызывается метод ВыполнитьЗапрос в параметрах которого, а также дополнительными методами устанавливается состав итогов, которые будут получены запросом. Выполнение данного метода осуществляет выборку данных и их предварительную обработку
Бухгалтерские счета
Работа с бухгалтерскими счетами очень похожа на работу с иерархическим справочником. Существует список счетов, имеющих стандартные атрибуты (Код, Наименование и др), и дополнительные реквизиты, задаваемые разработчиком. Реквизиты могут быть периодическими, т.е. хранить значение на определенную дату. Счета могут объединяться в группы, тогда счета, входящие в группу, называются субсчетами. Каждый счет обязательно принадлежит определенному плану счетов. В конфигурации может быть произвольное количество планов счетов, один из которых является основным.
Чтение файла DBF
В данном случае, мне кажется, что проще написать программу и прокомментировать ее, чем делать что-то еще. Вы уже такие продвинутые, раз добрались до этой главы! Я горжусь вами!
Файл = создатьОбъект("XBASE"); //создаем ссылку на файл DBF
Файл.ОткрытьФайл("catalog.dbf"); //открываем файл на диске
Файл.КодоваяСтраница(1); //задаем кодировку: 0 - windows, 1 - DOS
Если Файл.Открыта()=0 Тогда //проверяем, удалось ли открыть файл
........Сообщить("Не удалось открыть файл!");
КонецЕсли;
Файл.Первая(); //позиционируемся на первой записи
Пока Файл.ВКонце()=0 Цикл //пока не дошли до конца, крутим цикл
.......НомерЗаписи = Файл.НомерЗаписи(); //получаем номер текущей записи
.......НазвТовара = Файл.NAME; //получаем значение поля
.......Цена = Файл.ПолучитьЗначениеПоля("PRICE"); //так тоже можно, но чуть медленнее
.......Файл.Следующая(); //переходим на следующую запись
КонецЦикла;
Файл.Последняя(); //позиционируемся на первой записи
Пока Файл.ВНачале()=0 Цикл //пока не дошли до начала, крутим цикл
.......НазвТовара = Файл.NAME;
.......Цена = Файл.PRICE;
.......Файл. Предыдущая(); //переходим на предыдущую запись
КонецЦикла;
Для н = 1 По Файл.КоличествоЗаписей() Цикл //здесь все понятно, по-моему
......Файл.Перейти(н); //позиционируемся на определенной записи
.......НазвТовара = Файл.NAME;
.......Цена = Файл.PRICE;
КонецЦикла;
Файл.ЗакрытьФайл(); //не забывайте пожалуйста
Что можно скачать
Так как работа с метаданными плохо документирована самой фирмой 1С, то рекомендуется скачать следующий файл, который является файлом для Синтакс-помощника. В нем содержится описание работы с некоторыми методами объекта Метаданные.
metadata_als.zip
Распакуйте и поместите als-файл в каталог Program Files\1cv77\BIN и он будет подключен к Синтакс-помощнику.
Что такое нумератор?
Нумератор представляет собой объект метаданных, описывающий правила нумерации документов: тип и длина номера документа, его периодичность, необходимость контроля уникальности. Основное назначение нумератора - обеспечить возможность сквозной нумерации документов разного вида, для чего таким документам назначается одинаковый нумератор.
Периодичность. Этот реквизит устанавливает 2 важные характеристики нумератора: пределы контроля уникальности номеров документов и период повторяемости номеров. Если включен признак контроля уникальности номеров (см. ниже), "Периодичность" устанавливает, в каких пределах осуществлять этот контроль. Например, если установлено "В пределах дня", то уникальность номеров документов будет контролироваться в пределах суток: на следующие сутки номера документов могут повторяться. При включенной автоматической нумерации система будет присваивать очередной порядковый номер каждому новому документу. После завершения периода, установленного в реквизите "Периодичность", нумерация документов начнется с 1.
Длина. Устанавливает максимальную длину номера документа. Не размахивайтесь без нужды, "длинный" номер снижает производительность работы.
Тип. Группа "Тип" позволяет выбрать тип значения для номера документа - числовой или текстовый. Выбор текстового типа номера бывает полезен, когда используется сложная система нумерации документов, и номер документа может включать, помимо цифр, также буквы и символы-разделители.
Контроль уникальности. Если эта опция включена, то при вводе нового документа его номер проверяется на уникальность в пределах, установленных в реквизите "Периодичность".
Цикл по реквизитам справочника
кфгСпрСотр = Метаданные.Справочник("Сотрудники");
КолвоРеквизитов = кфгСпрСотр.Реквизит();
Для Ном=1 to КолвоРеквизитов Цикл
кфгРекв = кфгСпрСотр.Реквизит(Ном);
Идентификатор = кфгРекв.Идентификатор();
ПолныйИдентификатор = кфгРекв.ПолныйИдентификатор();
Синоним = кфгРекв.Синоним();
Комментарий = кфгРекв.Комментарий();
Тип = кфгРекв.Тип(); //"Строка", "Число", "Справочник"
Вид = кфгРекв.Вид(); //напр. "Сотрудники"
Длина = кфгРекв.Длина();
Точность = кфгРекв.Точность();
Периодический = кфгРекв.Периодический();
.....<и так далее>
КонецЦикла;
т.е. если вызвать метод Метаданные.Справочник(Х).Реквизит() без параметров, то он вернет общее количество реквизитов справочника Х в конфигурации. Если передать ему в качестве параметра номер или название реквизита, то он вернет реквизит справочника как объект конфигурации.
Цикл по справочникам
КолвоСправочниковВКонфигурации = Метаданные.Справочник();
Для Ном=1 to КолвоСправочниковВКонфигурации Цикл
кфгСпр = Метаданные.Справочник(Ном);
Идентификатор = кфгСпр.Идентификатор();
ПолныйИдентификатор = кфгСпр.ПолныйИдентификатор();
Синоним = кфгСпр.Синоним();
Комментарий = кфгСпр.Комментарий();
КоличествоУроней = кфгСпр.КоличествоУроней();
ПодчиненЛи = кфгСпр.Владелец().Выбран();
Владелец = кфгСпр.Владелец();
ИдентификаторВладельца = кфгСпр.Владелец().Идентификатор;
.....<и так далее>
КонецЦикла;
т.е. если вызвать метод Метаданные.Справочник() без параметров, то он вернет общее количество справочников в конфигурации. Если передать ему в качестве параметра номер или название справочника, то он вернет справочник как объект конфигурации.
Дата документа
Дата создания (или записи) - обязательный атрибут любого документа. Через него можно получить или назначить дату, с которой будет записан документ:
Док = СоздатьОбъект("Документ.РасходнаяНакладная");
Док.Новый();
Если Док.ДатаДок = '01.01.02' Тогда
..........Сообщить("С Новым Годом!");
КонецЕсли;
Дерево конфигурации (метаданные)
В окне конфигурации можно раскрывать списки объектов (константы, справочники, документы и т.д.). Объекты можно добавлять, удалять, редактировать, изменять их порядок, сортировать, писать для них описание. Каждый объект имеет свойства и контекстное меню (вызывается правой кнопкой мыши). Также к конфигурации относятся Интерфейсы и Права. Для их вызова нужно щелкнуть вкладки, расположенные внизу дерева конфигурации. Кроме того, когда окно дерева конфигурации активно в меню Действия становятся доступными пункты "Глобальный модуль", "Общие таблицы" и "Библиотека картинок". |
Добавление строк в таблицу значений
ТабЗнач.НоваяСтрока();
ТабЗнач.Номер = 1;
ТабЗнач.Сотрудник = "Иванов Иван Иванович"; //следите за типом колонки!
ТабЗнач.Должность = "Программист";
ТабЗнач.Оклад = 20000;
ТабЗнач.НоваяСтрока();
ТабЗнач.Номер = 2;
ТабЗнач.Сотрудник = "Петров Петр Петрович";
ТабЗнач.Должность = "Бухгалтер";
ТабЗнач.Оклад = 10000;
//обычно строки добавляются в цикле
СпрСотр = СоздатьОбъект("Справочник.Сотрудники");
СпрСотр.ВыбратьЭлементы();
Пока СпрСотр.ПолучитьЭлемент()=1 Цикл
.....ТабЗнач.НоваяСтрока();
.....ТабЗнач.Номер = СпрСотр.Код;
.....ТабЗнач.Сотрудник = СпрСотр.ТекущийЭлемент(); //следите за типом колонки!
.....ТабЗнач.Должность = СпрСотр.Должность;
.....ТабЗнач.Оклад = СпрСотр.Оклад;
КонецЦикла;
Добавление значений в список
Синтаксис: ДобавитьЗначение(<значение>,[<представление>]);
//у каждого значения в СпискеЗначений есть экранное представление
//если оно не указано, то используется стандартное строковое представление объекта
СписокЗнач.ДобавитьЗначение("Иванов Иван Иванович");
СписокЗнач.ДобавитьЗначение(Сотрудник);
СписокЗнач.ДобавитьЗначение(1,"Значение №1");
СписокЗнач.УстановитьЗначение(3,3,"Значение №3"); //установить новое значение и представление 3-й позиции
Доходы
Определять доходы магазина можно по регистру Доходы с помощью отчетов СводнаяТаблица и ОтчетПоРегистру, разработанных фирмой КИНТ.
Реверси
Документ "Доход"
Экранная форма документа выглядит следующим образом:
Модуль проведения:
Процедура ОбработкаПроведения()
Регистр.Доходы.Участник = Участник;
Регистр.Доходы.Статья = Статья;
Регистр.Доходы.Сумма = Сумма;
Регистр.Доходы.ДвижениеВыполнить();
Регистр.Кошельки.Кошелек = Кошелек;
Регистр.Кошельки.Сумма = Сумма;
Регистр.Кошельки.ДвижениеПриходВыполнить();
КонецПроцедуры
Документ "Перевод"
Данный документ переводит средства из одного кошелька в другой.
Модуль проведения:
Процедура ОбработкаПроведения()
Регистр.Кошельки.Кошелек = КошелекОткуда;
Регистр.Кошельки.Сумма = Сумма;
Регистр.Кошельки.ДвижениеРасходВыполнить();
Регистр.Кошельки.Кошелек = КошелекКуда;
Регистр.Кошельки.Сумма = Сумма;
Регистр.Кошельки.ДвижениеПриходВыполнить();
КонецПроцедуры
Документ "Письмо"
Данный документ имеет шапку и табличную часть. В шапке отражается, кто написал письмо, кому оно адресуется (адресат), тема письма, текст письма и флажок важности. Табличная часть содержит приложения к письму. Приложением может быть элемент любого справочника или любой документ с небольшим сопроводительным текстом. Данная почта отличается от Outlook тем, что позволяет прицеплять к письму конкретные объекты базы 1С, в которой работают пользователи. Т.е. пользователь может отправить такое письмо: "Света, посмотри, что творится с этой накладной!" и прицепить к письму саму накладную.
А на вкладке Приложения прицеплены сами товары с комментариями!
При сохранении письма производится следующее. У адресата устанавливается в единицу флажок ЕстьПисьмо в спр. Пользователи. Каждые несколько секунд (интервал настраивается в константах) производится проверка новой почты, если флажок взведен и есть новые непрочитанные письма, о которых еще не было оповещения, тогда пользователю выдается сообщение "Пришла почта! Прочитать?". Флажок ЕстьПисьмо снимается и утех писем, о которых пользователь был оповещен, устанавливается флажок БылоОповещение. Если пользователь ответит Да, тогда откроется его почтовый ящик (журнал Письма).
Документ "Потеря книги"
Экранная форма документа выглядит следующим образом:
Модуль формы см. в конфигурации "Мини-библиотека".
Модуль проведения:
Процедура ОбработкаПроведения()
СпрКниги = создатьОбъект("Справочник.Книги");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
СпрКниги.НайтиЭлемент(Книга);
СпрКниги.Статус = Перечисление.СтатусКниги.Списана;
СпрКниги.Читатель = 0;
СпрКниги.ДатаВыдачи = 0;
СпрКниги.СрокВозврата = 0;
СпрКниги.Записать();
КонецЦикла;
УстановитьРеквизитСправочника(Читатель, "Блокирован", Перечисление.ДаНет.Да, ДатаДок);
УстановитьРеквизитСправочника(Читатель, "Блокирован", Перечисление.ДаНет.Нет, ДатаДок + Константа.КолвоДнейБлокировки);
КонецПроцедуры
Документ "Приход"
Экранная форма документа Приход выглядит следующим образом:
Модуль проведения:
Процедура ОбработкаПроведения()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Регистр.ОстаткиМатериалов.Материал = Материал;
Регистр.ОстаткиМатериалов.Склад = Склад;
Регистр.ОстаткиМатериалов.Количество = Количество;
Регистр.ОстаткиМатериалов.ДвижениеПриходВыполнить();
КонецЦикла;
КонецПроцедуры
Документ "Продление книги"
Экранная форма документа выглядит следующим образом:
Модуль формы см. в конфигурации "Мини-библиотека".
Модуль проведения:
Процедура ОбработкаПроведения()
СпрКниги = создатьОбъект("Справочник.Книги");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Если Число(НовыйСрокВозврата)<>0 Тогда
СпрКниги.НайтиЭлемент(Книга);
СпрКниги.СрокВозврата = НовыйСрокВозврата;
СпрКниги.Записать();
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Документ "Расход"
Экранная форма документа Расход выглядит следующим образом (отличается только названием):
Модуль проведения:
Процедура ОбработкаПроведения()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Регистр.ОстаткиМатериалов.Материал = Материал;
Регистр.ОстаткиМатериалов.Склад = Склад;
Регистр.ОстаткиМатериалов.Количество = Количество;
Регистр.ОстаткиМатериалов.ДвижениеРасходВыполнить();
КонецЦикла;
КонецПроцедуры
Документ "Расход"
Экранная форма документа выглядит следующим образом:
Модуль проведения:
Процедура ОбработкаПроведения()
Регистр.Расходы.Участник = Участник;
Регистр.Расходы.Статья = Статья;
Регистр.Расходы.Сумма = -Сумма;
Регистр.Расходы.ДвижениеВыполнить();
Регистр.Кошельки.Кошелек = Кошелек;
Регистр.Кошельки.Сумма = Сумма;
Регистр.Кошельки.ДвижениеРасходВыполнить();
КонецПроцедуры
Документ "Сообщение"
Данный документ является коротким сообщением в общий чат. При сохранении документа он отражается в журнале Чат.
Документ "Возврат книги"
Экранная форма документа выглядит следующим образом:
Модуль формы см. в конфигурации "Мини-библиотека".
Модуль проведения:
Процедура ОбработкаПроведения()
СпрКниги = создатьОбъект("Справочник.Книги");
СпрЧитатели = СоздатьОбъект("Справочник.Читатели");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
СпрКниги.НайтиЭлемент(Книга);
Если СпрКниги.СрокВозврата < ДатаДок Тогда
СпрЧитатели.НайтиЭлемент(Читатель);
СпрЧитатели.КоличествоПредупреждений = СпрЧитатели.КоличествоПредупреждений + 1;
СпрЧитатели.Записать();
Если СпрЧитатели.КоличествоПредупреждений > Константа.МаксКолвоПредупреждений Тогда
УстановитьРеквизитСправочника(Читатель, "Блокирован",Перечисление.ДаНет.Да, ДатаДок);
УстановитьРеквизитСправочника(Читатель, "Блокирован",Перечисление.ДаНет.Нет, ДатаДок + Константа.КолвоДнейБлокировки);
КонецЕсли;
КонецЕсли;
СпрКниги.Статус = Перечисление.СтатусКниги.Свободна;
СпрКниги.Читатель = 0;
СпрКниги.ДатаВыдачи = 0;
СпрКниги.СрокВозврата = 0;
СпрКниги.Записать();
КонецЦикла;
КонецПроцедуры
Документ "Ввод начальных остатков"
Экранная форма документа выглядит следующим образом:
Модуль проведения:
Процедура ОбработкаПроведения()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Регистр.Кошельки.Кошелек = Кошелек;
Регистр.Кошельки.Сумма = Сумма;
Регистр.Кошельки.ДвижениеПриходВыполнить();
КонецЦикла;
КонецПроцедуры
Документ "Выдача книги"
Экранная форма документа выглядит следующим образом:
Модуль формы см. в конфигурации "Мини-библиотека".
Модуль проведения:
Процедура ОбработкаПроведения()
СпрКниги = создатьОбъект("Справочник.Книги");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
СпрКниги.НайтиЭлемент(Книга);
СпрКниги.Статус = Перечисление.СтатусКниги.Выдана;
СпрКниги.Читатель = Читатель;
СпрКниги.ДатаВыдачи = ДатаДок;
СпрКниги.СрокВозврата = СрокВозврата;
СпрКниги.Записать();
КонецЦикла;
КонецПроцедуры
Домашнее задание
Заставьте компьютер играть с самим собой. Но обязательно сделайте паузы между ходами, чтобы и человеку было интересно.
Охота на лис
Домашнее задание
Заставьте компьютер играть в эту игру. Придумайте алгоритм для поиска всех лис за минимальное число ходов.
Конкурент-магазин
Дополнение
Новый документ;
Идентификатор – "ИзменениеЦен", Синоним – "Изменение цен", Комментарий – "изменение цен товара";
Документ будет проводиться и перепроводиться;
Новый журнал – "ИзменениеЦен";
В окне свойств документа заполним позиции согласно таблицы;
Создадим форму документа;
Графы "СтЦенаП" и "СтЦенаР" – сделаем недоступными;
На поле ввода "Товар" повесим формулу ВыбТовар();
На поле ввода "ЦенаП" повесим формулу ЦенаП();
В модуль формы добавим две процедуры:
Процедура ВыбТовар()
СтЦенаП=Товар.ЦенаП.Получить(ДатаДок);
ЦенаП=Товар.ЦенаП.Получить(ДатаДок);
СтЦенаР=Товар.ЦенаР.Получить(ДатаДок);
ЦенаР=Товар.ЦенаР.Получить(ДатаДок);
// Получаем значения периодических реквизитов справочника на дату документа
КонецПроцедуры
//-----------------------------------------------
Процедура ЦенаП()
ЦенаР=Окр(ЦенаП*(1+(Константа.ПроцентНаценки/100)),2,1);
КонецПроцедуры
Перейдем к модулю документа;
Напишем процедуру обработки проведения документа:
Процедура ОбработкаПроведения()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
УстановитьРеквизитСправочника(Товар,"ЦенаП",ЦенаП);
УстановитьРеквизитСправочника(Товар,"ЦенаР",ЦенаР);
// Мы указываем периодические реквизиты элемента справочника,
// указанного в поле Товар и значения, которые они будут теперь иметь
КонецЦикла;
КонецПроцедуры
Сохраним конфигурацию;
Загрузим 1С:Предприятие;
Введем новый документ "Изменение цен" №1 от 04.10.2000;
В многострочную часть занесем товар "МПР-0342" (Кефир);
Укажем ему новую цену поступления – 6.50;
Цена реализации изменилась, и составила теперь – 8.78;
Подтвердим, что это нас устраивает нажатием на Enter, если нет, то можно отредактировать эту цену;
Заведем еще один товар – "ФРЯ-908" (Яблоки);
Новая цена поступления – 18, цена реализации – 25;
[ОК]. Проведем документ;
Откроем журнал ИзменениеЦен. Мы журнал не редактировали, таким он выглядит в 1С по умолчанию. Если будет желание, можете поэкспериментировать с изменением внешнего вида этого журнала в Конфигураторе;
Документ с галочкой. Галочка сиреневого цвета – документ проведен, но он не документ оперативного учета;
Посмотрим какие движения вызвал наш документ;
Он не изменял регистров, а внес изменения в реквизиты справочников;
Мы видим четыре строки. Пиктограммки показывают, что это изменение периодического реквизита. Указано в каком справочнике, какой реквизит, у какого элемента, когда принял новое значение;
Откроем теперь справочник "Номенклатура";
Найдем позицию "Кефир";
Меню Действия команда "История значения". Выберем "ЦенаП";
Мы видим, когда как менялась цена поступления этого товара;
Первая строчка с изображением руки – мы ввели цену вручную, при создании этого товара;
Вторая строка – листик с галочкой – мы изменили цену документом;
Ручное изменение цены никогда не имеет времени. Оно всегда располагается в самом начале дня. Изменение цены документом отслеживает время документа. Оно может располагаться в начале, середине либо конце дня, как было указано при сохранении документа. Если в течении дня было несколько таких документов, они расположатся в зависимости от указанного в них времени.
Закроем 1С:Предприятие;
2.18 Регистры по товарам.
Нами теперь уже накоплен некоторый опыт работы с документами и регистрами. Займемся конструированием регистров по товарам. Мы уже упоминали, что регистры бывают двух типов: остатков и оборотов. Заведем для примера оба типа регистров. А чтоб никто не догадался, назовем их так: регистр остатков – "ОстаткиТоваров" – для хранения информации по остаткам товаров, и регистр оборотов – "ОборотыТоваров" – для накопления информации по оборачиваемости товара.
Регистр "ОстаткиТоваров" будет содержать информацию: где хранится/ хранился товар, что хранилось, какого сорта. Следовательно, у нас будут измерения "Склад", "Товар", "Сорт". В задании сказано, что списание товара может идти либо по LIFO, либо по FIFO, либо по среднему. Для первых двух вариантов нам надо хранить еще информацию – когда этот товар поступил на склад. Удобнее всего будет завести еще одно измерение – "Партия" – типа документ прихода товара ("ПриходнаяНакладная"). В документе хранятся дата и время, и можно без труда отсортировать их по порядку постановки на учет. Ресурсы регистра – то, что хранит регистр. Нас будет интересовать во-первых, количество товара в основной единице измерения товара, во-вторых его сумма по цене поступления – цена учета, и в-третьих сумма по цене документа – для определения полученного навара. Ценой документа в случае приходной накладной и накладной на перемещение будет цена поставки, а в случае расходной накладной – цена реализации. Реквизит у нас будет один – "ФлагДвижения" тип Число 1.0. В нем мы будем отражать характер движения, он будет равен 1 при движении Контрагент-Склад/Склад-Контрагент, и 2 при движении Склад-Склад. Движения по регистру у нас будут – приход для прихода товара на склад и расход для расхода товара со склада. Данные по регистру сведем в таблицу:
Идентификатор: ОстаткиТоваров Тип: Остатки Периодичность: - |
Дополнение
Поставщик
От кого пришел товар
С.Контрагенты
Договор
Основание отгрузки товара
С.Договора
Склад
Куда пришел товар
С.Склады
Дополнение
Здесь:
+ - неотрицательный;
И – итог по колонке;
Создадим в конфигураторе эти документ и журнал;
В регистре "ОстаткиТоваров" исправим тип измерения "Партия" с "Неопределенный" на "Д.ПриходнаяНакладная";
Создаем экранную форму документа;
В свойствах поля "Договор" на закладке "Дополнительно" укажем, что оно связано с полем "Поставщик" (как в документе "Приход денег");
В свойствах колонки "Ед" на закладке "Дополнительно" укажем, что она связана с колонкой "Товар" (справочник "Единицы" принадлежат справочнику "Номенклатура");
В свойствах колонки "Товар" на закладке "Дополнительно" напишем формулу Товар(). Эта процедура будет заполнять колонки "Сорт", "Кол", "Ед", "КолО", "Цена", "Сумма" сразу после ввода товара;
Для того чтобы вводить сорт по умолчанию, создадим константу "СортПоУмолчанию" типа С.Сорт;
В модуль формы добавим процедуру:
Процедура Товар()
Если Товар.Выбран()=1 Тогда
Если Сорт.Выбран()=0 Тогда
// Если сорт не выбран (сорт может быть выбран если редактируется
// существующая строка)
Сорт=Константа.СортПоУмолчанию;
КонецЕсли;
Если Кол=0 Тогда
Кол=1;
КонецЕсли;
СпрЕд=СоздатьОбъект("Справочник.Единицы");
// создаем в памяти копию справочника единиц
СпрЕд.ИспользоватьВладельца(Товар);
// указываем, что нам нужны только единицы, принадлежащие
// выбранному товару
СпрЕд.ВыбратьЭлементы();
Пока СпрЕд.ПолучитьЭлемент()=1 Цикл
// перебираем справочник единиц поэлементно
Если СпрЕд.Ед=Товар.ЕдИзм Тогда
// мы нашли единицу соответствующую основной единице товара
Ед=СпрЕд.ТекущийЭлемент();
// передаем в реквизит табличной части найденное значение
Прервать;
// прерываем обход по циклу. То, что мы искали уже найдено
КонецЕсли;
КонецЦикла;
КолО=Окр(Кол*(Ед.Коэффициент),2,1);
// пересчитываем количество в количество основных единиц
Цена=Окр(Товар.ЦенаП.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
// определяем цену товара с учетом текущего сорта
Сумма=Окр(КолО*Цена,2,1);
// вычисляем сумму
КонецЕсли;
КонецПроцедуры
Теперь нам надо по выбору сорта менять цену и соответственно сумму. В свойствах колонки "Сорт" на закладке "Дополнительно" напишем формулу Сорт();
В модуль формы добавляем процедуру:
Процедура Сорт()
Если Сорт.Выбран()=1 Тогда
Цена=Окр(Товар.ЦенаП.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
Сумма=Окр(КолО*Цена,2,1);
КонецЕсли;
КонецПроцедуры
Теперь нам надо, если изменится значение в колонке "Кол", то менялись бы "КолО" и "Сумма". В свойствах колонки "Кол" на закладке "Дополнительно" напишем формулу Кол();
В модуль формы добавляем процедуру:
Процедура Кол()
КолО=Окр(Кол*(Ед.Коэффициент),2,1);
Сумма=Окр(КолО*Цена,2,1);
КонецПроцедуры
Теперь нам надо, если изменим единицу измерения, то пересчитывалось бы "КолО" и "Сумма". В свойствах колонки "Ед" на закладке "Дополнительно" напишем формулу Ед();
В модуль формы добавляем процедуру:
Процедура Ед()
КолО=Окр(Кол*(Ед.Коэффициент),2,1);
Сумма=Окр(КолО*Цена,2,1);
КонецПроцедуры
Колонки "КолО" и "Сумма" сделаем недоступными для редактирования;
Цена в приходной накладной у нас устанавливается из справочника. Оставим себе возможность изменять цену в приходной накладной;
При изменении цены накладной должна пересчитываться сумма. В свойствах колонки "Цена" на закладке "Дополнительно" напишем формулу Цена();
В модуль формы добавляем процедуру:
Процедура Цена()
Сумма=Окр(КолО*Цена,2,1);
КонецПроцедуры
При изменении поля шапки "Поставщик", поле "Договор" должно очищаться. В свойствах поля "Поставщик" на закладке "Дополнительно" напишем формулу Поставщик();
В модуль формы добавляем процедуру:
Процедура Поставщик()
Договор=ПолучитьПустоеЗначение("Справочник.Договора");
// Функция ПолучитьПустоеЗначение() возвращает пустое значение
// заданного типа
КонецПроцедуры
Добавим в форму документа, ниже табличной части, элемент диалога Текст. В свойствах текста на закладке "Общие" очистим содержимое поля "Заголовок". На закладке "Дополнительно" в поле "Формула" пишем: Итог("КолО"). Функция Итог() вернет итог по указанной колонке таблицы если для реквизита табличной части документа была указана опция "Итог по колонке - да";
Добавим в форму документа, рядом с предыдущим полем, еще один элемент диалога Текст. В свойствах текста на закладке "Общие" очистим содержимое поля "Заголовок". На закладке "Дополнительно" в поле "Формула" пишем: Итог("Сумма");
Экранная форма почти готова. Давайте добавим в документ печатную форму. В остальные документы мы печатные формы добавлять не будем. Но если появится желание, то никто не запрещает;
Добавим в форму документа, правее кнопки [Закрыть], элемент диалога Кнопка;
Заголовок ей дадим "Печать". Формула Печать();
В модуль формы добавляем процедуру:
Процедура Печать()
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Таблица ");
Таб.ВывестиСекцию("Шапка");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
НС=НомерСтроки;
// атрибут НомерСтроки возвращает номер текущей строки
// табличной части
Таб.ВывестиСекцию("Строка");
КонецЦикла;
ИтогПр=Формат(Итог("Сумма"),"ЧПДС");
// В переменную ИтогПр мы выведем сумму прописью
Таб.ВывестиСекцию("Подвал");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Перейдем на закладку "Таблица" формы документа;
Создадим шаблон таблицы такого, примерно, вида:
Строка 10 – Тип "Выражение", Строки 1, 3-6, 13, 14 – Тип "Шаблон";
Перейдем в модуль документа;
Напишем процедуру проведения документа:
Процедура ОбработкаПроведения()
// Долг за поставленный нам товар возрос
Регистр.Взаиморасчеты.Контрагент = Поставщик;
Регистр.Взаиморасчеты.Договор = Договор;
Регистр.Взаиморасчеты.Сумма = Итог("Сумма");
Регистр.Взаиморасчеты.ФлагДвижения = 1;
Регистр.Взаиморасчеты.ДвижениеПриходВыполнить();
// по каждой строке
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
// Увеличиваем количество товара на складе
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = ТекущийДокумент();
Регистр.ОстаткиТоваров.Количество = КолО;
Регистр.ОстаткиТоваров.СуммаП = Сумма;
Регистр.ОстаткиТоваров.СуммаД = Сумма;
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
// Указав команду ПривязыватьСтроку() мы к каждой записи по движению
// регистра укажем – какая конкретно строка документа произвела это движение
Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
// Добавляем запись о росте товарооборота
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолО;
Регистр.ОборотыТоваров.СуммаУ = Сумма;
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
// Оборотный регистр осуществляет не приход/расход а движение
КонецЦикла;
КонецПроцедуры
Условия, при которых документ не должен проводиться напишите сами, если хотите.
В этой процедуре мы совершили движение сразу по трем регистрам.
По одному - "Взаиморасчеты" – сразу на весь документ суммой, и по двум другим построчно.
Сколько строк будет в документе, столько и движений по каждому регистру.
Перейдем теперь к журналу "Накладные";
Добавим графу. Назовем ее "Кол". Для графы выберем значение Документ.ПриходнаяНакладная.КолО. Как мы видим в списке доступных реквизитов из табличной части присутствуют только те, которые помечены итогом по колонке. В журнал в дополнительную графу тоже попадут значения итога по указанной колонке;
Добавим еще графу – "Сумма". Документ.ПриходнаяНакладная.Сумма;
Создадим форму журнала;
Отредактируем размеры и расположение граф;
Сохраним конфигурацию;
Загрузим 1С:Предприятие;
Заполним сперва новую константу значением – 1 сорт;
Создадим приходную накладную №1 от 04.10.2000;
Пусть нам фирма "Винни-Пух и все все все" по договору №12 на склад №1 поставит партию товара;
Введем товар, к примеру кефир. Мы видим, что значения в остальных колонках заполнились автоматически;
Давайте изменим количество на 5. Посмотрим как изменились значения в других колонках;
А теперь единицы на ящики;
И сорт поставим второй;
И вообще, это будет не кефир, а стулья;
Введем еще несколько позиций;
Нажмем [Печать]. Наша накладная готова к посылке на принтер;
Теперь сохраним и проведем эту накладную;
Откроем журнал "Накладные";
Найдем нашу накладную;
Посмотрим какие движения она совершила;
Как мы и хотели, накладная двинула три регистра;
Сделайте еще несколько накладных от разных поставщиков, по разным договорам на разные склады;
Посмотрите, как изменились данные в отчете "Взаиморасчеты";
2.20 Отчет по остаткам на складе.
Мы ввели кучу приходных накладных. Теперь нам интересно знать, что на каком складе лежит. Сделаем отчет.
Отчет "ОстаткиНаСкладе";
Вставим в экранную форму два элемента диалога;
Первый: поле ввода "ВыбДата" тип Дата;
Второй: поле ввода "ВыбСклад" тип С.Склады;
Соответственно приставим к ним текстовые поля с надписью, что есть что (вообще это удобно делать через меню Вставить командой "Элемент диалога...", либо аналогичной кнопкой из панели инструментов) ;
В модуле пропишем процедуру:
Процедура ПриОткрытии()
ВыбДата=РабочаяДата();
// РабочаяДата – дата, на которую установлена в данный момент 1С.
КонецПроцедуры
Заполним процедуру Сформировать(). Эта процедура вызывается одноименной кнопкой [Сформировать]. Там она прописана в поле "Формула";
Процедура Сформировать()
ТабЗн=СоздатьОбъект("ТаблицаЗначений");
// создаем динамическую 2-х мерную таблицу
ТабЗн.НоваяКолонка("Товар","Справочник.Номенклатура");
ТабЗн.НоваяКолонка("Сорт","Справочник.Сорт");
ТабЗн.НоваяКолонка("Ост","Число",17,2);
// указываем какие колонки будет содержать наша динимическая таблица
РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");
// создаем в памяти копию регистра остатков
РегОст.ВременныйРасчет(1);
// указываем, что из этого регистра нам, возможно, надо будет получить данные
// на момент времени отличный от текущего
РассчитатьРегистрыНа(ВыбДата);
// указываем на какой момент времени надо получить данные из регистров
РегОст.ВыбратьИтоги();
// открываем выборку итогов из регистра (на указанный момент времени)
Пока РегОст.ПолучитьИтог()=1 Цикл
// получаем очередной итог
ТСклад=РегОст.Склад;
Если ТСклад=ВыбСклад Тогда
// если текущий итог по выбранному складу
ТабЗн.НоваяСтрока();
// добавляем в динамическую таблицу новую строку
ТабЗн.Товар=РегОст.Товар;
ТабЗн.Сорт=РегОст.Сорт;
ТабЗн.Ост=РегОст.Количество;
// заполняем поля д. таблицы
КонецЕсли;
КонецЦикла;
РегОст="";
// убираем из памяти копию регистра. Она нам больше не нужна
СтрокаН=0;
ТабЗн.ВыбратьСтроку(СтрокаН,"Просмотр содержимого таблицы");
// Это мы делаем, чтобы просмотреть содержимое динамической таблицы
// у нас будут строки с одинаковым товаром и сортом, они возникли из-за
// наличия измерения "Партия" нам надо их объединить
ТабЗн.Свернуть("1,2","3");
// методом Свернуть() мы объединяем строки у которых содержимое
// в колонках 1 и 2 одинаковое, а колонку 3 мы суммируем
СтрокаН=0;
ТабЗн.ВыбратьСтроку(СтрокаН,"Просмотр содержимого таблицы");
// смотрим что получилось. Строки у нас идут вразнобой
ТабЗн.Сортировать("1+,2+");
// отсортируем их. сперва сортируем по убыванию колонку 1,
// а внутри нее, тоже по убыванию, колонку "Сорт"
СтрокаН=0;
ТабЗн.ВыбратьСтроку(СтрокаН,"Просмотр содержимого таблицы");
// смотрим на результат
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Таблица");
Таб.ВывестиСекцию("Шапка");
ТТовар="@#$%&";
// такого товара у нас, надеюсь, не будет
ТабЗн.ВыбратьСтроки();
// открываем выборку строк из д. таблицы
Пока ТабЗн.ПолучитьСтроку()=1 Цикл
Товар=ТабЗн.Товар;
Тов=СокрЛП(Товар.Код)+" ("+СокрЛП(Товар.Наименование)+")";
Сорт=ТабЗн.Сорт;
Ост=ТабЗн.Ост;
Ед=Строка(Товар.ЕдИзм);
Если ТТовар<>Товар Тогда
// если товар из д. таблицы не совпадает с переменной ТТовар
Таб.ВывестиСекцию("Товар");
// выводим эту секцию таблицы для печати
ТТовар=Товар;
Иначе
// товар совпадает, только сорт другой
Таб.ВывестиСекцию("Сорт");
// выводим эту секцию
КонецЕсли;
КонецЦикла;
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Теперь создаем шаблон для печатной таблицы;
Загружаем 1С:Предприятие;
Смотрим, что нам покажет отчет на разные даты по разным складам;
Глава 8
2.21 FIFO/LIFO/По-среднему.
Любителей футбола просим не беспокоится. Речь у нас пойдет не о FIFA, а о способах списания товара при разных системах учета. Бухгалтерам объяснять, что это такое, не нужно. Для остальных кратенько поясним.
FIFO (First Input First Output) – это такая система, при которой ранее пришедшие партии товара списываются первыми. Цена списания – цена партии товара из которой списывают товар.
LIFO (Last Input First Output) – а это такая система, при которой последняя пришедшая партия товара списывается в первую очередь. Цена списания – цена партии товара из которой списывают товар.
По-среднему – здесь вообще партии не нужны. Цена списания – средняя цена остатка партий товара на складе.
Мы должны при начале работы указать, какой системой списания мы будем в дальнейшем пользоваться. Перечень возможных систем учета мы будем держать в перечислении.
Создаем новый виз перечисления – "МетодСписания";
Добавим значения ФИФО, ЛИФО, По_Среднему. В представлении можно и латинскими буквами, а в идентификаторах – русскими, чтобы при наборе кода лишний раз язык не переключать;
Для хранения выбранного нами типа списания заведем константу;
Создаем константу "МетодСписания" тип П.МетодСписания;
При начале работы с программой учета надо обязательно выставлять способ списания. И в последующем не менять его. Пусть программа при начале работы проверит, выбран ли способ списания, если не выбран, то предложить выбрать, а если выбран – ничего не делать. Запрещать редактирование мы не будем, нам охота поэкспериментировать.
Входим в окно с деревом метаданных;
Меню Действия команда "Глобальный модуль";
Появилось окно глобального модуля. Подробнее в "Описание встроенного языка" т. 1;
Пишем процедуру:
Процедура ПриНачалеРаботыСистемы()
// предопределенная процедура, запускается при начале работы
// в 1С:Предприятии
Перем Значение;
// Объявляем переменную
Если Константа.МетодСписания.Выбран()=0 Тогда
// если константа не заполнена
Рез=ВвестиЗначение(Значение,"Выберите способ списания","Перечисление.МетодСписания");
// просим выбрать способ списания. Рез=1, если выбор произведен,
// 0 – если нет
Если Рез=1 Тогда
Константа.МетодСписания=Значение;
// установим константе выбранное значение
Иначе
СтатусВозврата(0);
// Мы просили выбрать значение, а Вы этого не сделали.
// С 1С работать не будете!
// СтатусВозврата определяет, как должно завершиться событие вызвавшее
// предопределенную процедуру. В данном случае открытие системы должно
// завершиться неудачей. Т.е. 1С:Предприятие закроется.
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Загрузим 1С:Предприятие и попробуем сперва отказаться от выбора, а потом выбрать FIFO. Посмотрим значения констант;
Создадим две приходные накладные на Склад №3 с одинаковым товаром и сортом и количеством, но с разной ценой прихода. Пусть это будет кефир первого сорта по 20 штук в накладной №6 по цене 6.00 а в накладной №7 по 7.00, яблоки первого сорта по 50 штук в накладной №6 по цене 17.00 а в накладной №7 по 19.00 и яблоки второго сорта по 50 штук в накладной №6 по цене 16.00 а в накладной №7 по 16.40. Накладная №6 должна быть от 06.10.2000, а №7 от 07.10.2000;
Проведем накладные;
Все остальные накладные надо распровести. Они нам будут только мешать и излишне усложнять картину. Для этого;
Откроем журнал "Накладные";
Установим курсор на ненужную нам накладную;
Меню Действия команда "Сделать документ не проведенным";
Подтвердим отмену проведения документа;
Галочка с пиктограммы документа исчезла – документ не проведен;
Проверим по отчету остатки на складе №3;
2.22 Расходная накладная.
У нас на одном из складов есть некоторое количество товара. Пришло время создать расходную накладную. Во многом она у нас будет повторять приходную. Похожий набор полей шапки, только вместо поля "Поставщик" мы введем поле "Покупатель". Номер документа у нас будет зависеть не от бухгалтерии контрагента, а от нашей. Нам еще надо учесть, что будет позднее создана накладная на перемещение, и у расходных накладных и у накладных на перемещение должна быть общая нумерация. Это решается введением Нумератора.
В дереве метаданных в разделе Документы найдем подраздел Нумераторы;
Создадим новый нумератор "Накладные";
Периодичность – в пределах года, длина – 5, цифровой, контроль уникальности – да;
Расходная накладная будет располагаться в уже существующем журнале "Накладные". Данные по документу расходная накладная сведем в таблицу:
Идентификатор: РасходнаяНакладная Журнал: Накладные Нумератор: Накладные Периодичность: Длина: Тип: Уникальность: Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?: |
Дополнение
Покупатель
Кому ушел товар
С.Контрагенты
Договор
Основание отгрузки товара
С.Договора
Склад
Откуда отгрузили товар
С.Склады
Дополнение
Создадим новый документ;
Заполняем свойства и реквизиты согласно таблицы;
Создаем форму документа;
Редактируем форму накладной по аналогии с приходной накладной;
Поле реквизита "НомерДок" делаем недоступным для редактирования;
Формулы в реквизиты диалога ставим такие же как и в приходной накладной. За исключением Поставщик(), ее заменяем на Покупатель(). И убираем процедуру из колонки "Цена", эту колонку делаем недоступной для редактирования;
Процедуры в модуль документа заносим из модуля формы приходной накладной. Только везде ЦенаП меняем на ЦенаР, и меняем название процедуры Поставщик() на Покупатель(), и убираем процедуру Цена();
Текстовые поля с итогами по колонкам таблицы можно просто скопировать из формы документа приходная накладная;
У нас цена реализации зависит от даты. Мы хотим, чтобы при изменении даты документа цены в строках документа соответственно менялись;
Добавим функцию ДатаДок() в поле реквизита "ДатаДок";
В модуль формы добавим процедуру:
Процедура ДатаДок()
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Если Сорт.Выбран()=1 Тогда
Цена=Окр(Товар.ЦенаР.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
Сумма=Окр(КолО*Цена,2,1);
Иначе
Цена=0;
Сумма=0;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
// Процедура простая и в комментариях не нуждается
При заполнении накладной нам надо помнить, чего сколько на каком складе у нас лежит. В 1С для такой ситуации есть специальный механизм подбора. Реализуем его в нашей расходной накладной. Но сперва, для подбора, создадим особую форму списка справочника товаров.
Войдем в окно редактирования свойств справочника Номенклатура;
Нажимаем [Формы списка >];
Выпал список. Выберем пункт "Редактировать";
Появилось окно редактирования списка форм списка справочника;
[Новый];
Введем идентификатор "ДляПодбора". [ОК];
Курсор на новой форме списка "ДляПодбора";
Нажмем [Для выбора];
Галочка во второй колонке переместилась, и встала напротив "ДляПодбора";
[Открыть];
В форме списка оставим только поля "Код" и "Наименование";
Через меню Вставить командой "Текст" выберем элемент диалога текст для вставки;
Укажем ему место для вставки в табличной части. Добавилась новая колонка. В ней мы будем выводить остаток товаров на рабочую дату;
В свойствах этой колонки типа Текст пишем заголовок "Ост";
В формулу пишем функцию Ост();
Добавим в экранную форму поле ввода "Склад" типа С.Склады – остатки у нас будут по конкретному складу. Это поле сделаем недоступным;
В модуль формы списка добавим функцию:
Функция Ост()
ТекТовар=ТекущийЭлемент();
// Получаем текущий товар в строке
КолТов=Регистр.ОстаткиТоваров.СводныйОстаток(Склад,
ТекущийЭлемент(),,,"Количество");
// Получаем суммарный остаток по ресурсу "Количество"
// по измерениям "Склад" и "Товар", по остальным измерениям суммируем
Если КолТов<=0 Тогда
Возврат("");
// если товара на складе нет в поле Ост вернем пустую строку
Иначе
Возврат(КолТов);
// иначе вернем количество остатка
КонецЕсли;
КонецФункции
Вернемся к форме документа расходная накладная;
Добавим в экранную форму кнопку;
Заголовок у нее будет "Подбор", формула – Подбор();
В модуль формы добавим две процедуры:
Процедура Подбор()
// Эта процедура запускается по нажатию кнопки [Подбор]
ОткрытьПодбор("Номенклатура","ДляПодбора");
// Инициализируем механизм подбора и указываем, что подбирать мы
// будем из справочника Номенклатура, используя форму списка "ДляПодбора"
УстановитьЗначениеВПодборе("Склад",Склад);
// В форму подбора в поле "Склад" передаем значение склада из
// текущего документа
КонецПроцедуры
//-----------------------------------------------
Процедура ОбработкаПодбора(ВыбТов)
// Предопределенная процедура, срабатывающая по событию – выбор
// элемента ВыбТов из справочника
КолОст=Регистр.ОстаткиТоваров.СводныйОстаток(Склад,
ВыбТов,,,"Количество");
// Проверим остаток
Если КолОст<=0 Тогда
Возврат;
// если остаток на складе отсутствует, завершаем процедуру
КонецЕсли;
ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
// временная динамическая таблица
ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
// еще одна временная динамическая таблица
ТабЗн2.НоваяКолонка("Сорт","Справочник.Сорт",,,"Сорт",5);
ТабЗн2.НоваяКолонка("Остаток","Число",17,2,"Остаток",17);
// колонки д. таблицы
РегО=СоздатьОбъект("Регистр.ОстаткиТоваров");
РегО.УстановитьФильтр(Склад,ВыбТов);
// в копии регистра остатков нас будут интересовать
// итоги по конкретному складу и конкретному товару
РегО.ВыгрузитьИтоги(ТабЗн1,1,1);
// перегрузим итоги в д. таблицу
РегО="";
ТабЗн1.ВыбратьСтроки();
Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
Ост=ТабЗн1.Количество;
Если Ост>0 Тогда // есть что проверять
// если есть остаток, мы его перенесем во вторую д. таблицу
Срт=ТабЗн1.Сорт;
ТабЗн2.НоваяСтрока();
ТабЗн2.Сорт=Срт;
ТабЗн2.Остаток=Ост;
КонецЕсли;
КонецЦикла;
ТабЗн2.Свернуть("1","2");
// просуммируем по сортам и получим количество товара по каждому сорту
ВыбСтрока=1;
Если ТабЗн2.ВыбратьСтроку(ВыбСтрока,
СокрЛП(ВыбТов.Код)+" ("
+СокрЛП(ВыбТов.Наименование)+")")=1 Тогда
// Выберем строку с нужным сортом
НоваяСтрока();
// создаем в документе новую строку
Товар=ВыбТов;
// заполняем поле "Товар"
СортВыб=ТабЗн2.ПолучитьЗначение(ВыбСтрока,"Сорт");
// по выбранной строке получаем сорт
КолОст=ТабЗн2.ПолучитьЗначение(ВыбСтрока,"Остаток");
// и остаток
Сорт=СортВыб;
СпрЕд=СоздатьОбъект("Справочник.Единицы");
СпрЕд.ИспользоватьВладельца(Товар);
СпрЕд.ВыбратьЭлементы();
Пока СпрЕд.ПолучитьЭлемент()=1 Цикл
Если СпрЕд.Ед=Товар.ЕдИзм Тогда
Ед=СпрЕд.ТекущийЭлемент();
Прервать;
КонецЕсли;
КонецЦикла;
// это уже было...
Цена=Окр(Товар.ЦенаР.Получить(ДатаДок)*(Сорт.Процент/100),2,1);
КолВыб=0;
Если ВвестиЧисло(КолВыб,СокрЛП(ВыбТов.Код)
+"/"+СокрЛП(Строка(СортВыб)+" кол:"
+Строка(КолОст)),8,2,0)=1 Тогда
// Введем нужное нам количество
Если КолВыб>КолОст Тогда
// сравним введенное нами количество с остатком
КолВыб=КолОст;
КонецЕсли;
Кол=КолВыб;
КолО=Окр(Кол*(Ед.Коэффициент),2,1);
Сумма=Окр(КолО*Цена,2,1);
КонецЕсли;
АктивизироватьСтроку();
// установим курсор в документе на строку, которую мы ввели
КонецЕсли;
КонецПроцедуры
Перейдем теперь к написанию модуля проведения документа;
Напишем в модуль документа следующее:
Процедура ОбработкаПроведения()
РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");
Если СравнитьТА()=-1 Тогда
// Проверяем, не проводится ли документ ранее точки актуальности итогов
РегОст.ВременныйРасчет(1);
РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;
// Проверка на наличие на остатке
ВыбратьСтроки();
ФлагОтказа=0;
Пока (ПолучитьСтроку()>0) Цикл
Остат=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество");
Если Остат
Сообщить("Нет товара № "
+СокрЛП(Товар.Код)+"/"
+СокрЛП(Сорт.Наименование)+" в колич. "
+КолО+" (имеется "+Остат+")");
ФлагОтказа=1;
КонецЕсли;
КонецЦикла;
// аналогичную часть кода см. в отчете ОстаткиНаСкладе
Если ФлагОтказа=1 Тогда
НеПроводитьДокумент();
Возврат;
КонецЕсли;
// Это см. документы Приход/Расход денег
// По регистру взаиморасчетов
Регистр.Взаиморасчеты.Контрагент = Покупатель;
Регистр.Взаиморасчеты.Договор = Договор;
Регистр.Взаиморасчеты.Сумма = Итог("Сумма");
Регистр.Взаиморасчеты.ФлагДвижения = 2;
Регистр.Взаиморасчеты.ДвижениеРасходВыполнить();
Если Константа.МетодСписания=Перечисление.МетодСписания.ФИФО Тогда
// Здесь будет записана методика списания по FIFO
ИначеЕсли Константа.МетодСписания=Перечисление.МетодСписания.ЛИФО
Тогда
// Здесь будет записана методика списания по LIFO
ИначеЕсли
Константа.МетодСписания=Перечисление.МетодСписания.По_среднему
Тогда
// Здесь будет записана методика списания по-среднему
КонецЕсли;
КонецПроцедуры
Начнем описание методик с FIFO;
Заместо строки "// Здесь будет записана методика списания по FIFO" напишем:
// Здесь будет записана методика списания по FIFO
ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
// временная таблица
ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
// еще одна временная таблица
ТабЗн2.НоваяКолонка("Партия","Документ.ПриходнаяНакладная");
ТабЗн2.НоваяКолонка("КоличествоП","Число",14,2);
ТабЗн2.НоваяКолонка("СуммаП","Число",19,2);
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолВыб=КолО;
РегОст.УстановитьФильтр(Склад,Товар,Сорт);
РегОст.ВыгрузитьИтоги(ТабЗн1,1,1);
// см. операцию подбора
ТабЗн1.Свернуть("4","5,6");
// а здесь интересно: Структура ТабЗн1 после выгрузки будет аналогична
// структуре регистра. Реквизит "Партия" в регистре стоит на 4-ой
// позиции, значит и колонка "Партия" – 4-ая, Колонки "Количество"
// и "СуммаП" – соответственно 5-ая и 6-ая
ТабЗн1.ВыбратьСтроки();
Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
Прт=ТабЗн1.Партия;
Ост=ТабЗн1.Количество;
Сум=ТабЗн1.СуммаП;
Если Ост>0 Тогда // есть что проверять
ТабЗн2.НоваяСтрока();
ТабЗн2.Партия=Прт;
ТабЗн2.КоличествоП=Ост;
ТабЗн2.СуммаП=Сум;
КонецЕсли;
КонецЦикла;
// Заполняем промежуточную таблицу
ТабЗн1.Очистить();
// Удаляем все записи и колонки из ТабЗн1
ТабЗн2.Сортировать("1+",1);
// Сортируем по документам в порядке возрастания даты (FIFO)
// Более ранние партии вверху
ТабЗн2.ВыбратьСтроки();
Пока ТабЗн2.ПолучитьСтроку()=1 Цикл
Ост=ТабЗн2.КоличествоП;
Сум=ТабЗн2.СуммаП;
ЦенаПП=Окр(Сум/Ост,2,1);
// определяем цену текущей партии
Парт=ТабЗн2.Партия;
// а вот и сама партия
Если КолВыб>Ост Тогда // Ост
// требуемое количество больше, чем остатки в текущей партии,
// здесь спишем сколько есть, а что осталось, из более поздней
// партии
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = Ост;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
// Про обороты не забыть!
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Ост;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
// это сколько остатков нам не хватает до полного счастья
Иначе
// В партии товара больше, чем мы запрашиваем.
// Списываем сколько запрашиваем
Если КолВыб>0 Тогда // КолВыб
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолВыб;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолВыб,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолВыб;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ТабЗн2.УдалитьСтроки();
// удаляем строки из временной таблицы.
// Готовим ее под следующую строку документа
КонецЦикла;
Здесь мы воспользовались для определения партий механизмом прямой выгрузки данных из регистра в таблицу значений.
Теперь опишем методику списания по LIFO. Мы, конечно можем, воспользоваться предыдущим примером, заменив строку
ТабЗн2.Сортировать("1+",1);
На ТабЗн2.Сортировать("1-",1);
// Сортировка документов по убывающей. Последний – сверху
Но мы легких путей не ищем! Воспользуемся механизмом запроса.
Заместо строки "// Здесь будет записана методика списания по LIFO" напишем:
// Здесь будет записана методика списания по LIFO
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
КолСпис=КолО;
Запрос="";
ТекстЗапроса="";
Если ИтогиАктуальны()=0 Тогда
ТекстЗапроса="
|Период с ДатаДок по ДатаДок;";
КонецЕсли;
ТекстЗапроса=ТекстЗапроса+"
|РегСклад=Регистр.ОстаткиТоваров.Склад;
|РегТовар=Регистр.ОстаткиТоваров.Товар;
|РегСорт=Регистр.ОстаткиТоваров.Сорт;
|РегПартия=Регистр.ОстаткиТоваров.Партия;
|РегКолич=Регистр.ОстаткиТоваров.Количество;
|РегСумма=Регистр.ОстаткиТоваров.СуммаП;
|Группировка РегПартия Упорядочить по РегПартия.ДатаДок;
|Функция КолКонОст=КонОст(РегКолич);
|Функция СумКонОст=КонОст(РегСумма);
|Условие (РегСклад=Склад);
|Условие (РегТовар=Товар);
|Условие (РегСорт=Сорт);";
Запрос=СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Документ не проведен");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Пока Запрос.Группировка("РегПартия",-1)=1 Цикл
// В методе Группировка флаг – 1 указывает, что сортировка по запросу
// идет в порядке убывания. Более поздние документы идут первыми
Если КолСпис=0 Тогда
Прервать;
КонецЕсли;
ПартияСписания=Запрос.РегПартия;
Если Запрос.КолКонОст>КолСпис Тогда
Списывать=КолСпис;
Стоимость=Окр((Запрос.СумКонОст/Запрос.КолКонОст)*Списывать,2,1);
ИначеЕсли Запрос.КолКонОст=КолСпис Тогда
Списывать=КолСпис;
Стоимость=Запрос.СумКонОст;
ИначеЕсли Запрос.КолКонОст
Списывать=Запрос.КолКонОст;
Стоимость=Запрос.СумКонОст;
КонецЕсли;
КолСпис=КолСпис-Списывать;
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = ПартияСписания;
Регистр.ОстаткиТоваров.Количество = Списывать;
Регистр.ОстаткиТоваров.СуммаП = Стоимость;
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Списывать;
Регистр.ОборотыТоваров.СуммаУ = Стоимость;
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
КонецЦикла;
Теперь опишем алгоритм списания по-среднему:
// Здесь будет записана методика списания по-среднему
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество");
// Получаем суммарный остаток по указанным измерениям
// по данному ресурсу
СумОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"СуммаП");
ЦенОст=Окр(СумОст/КолОст,2,1);
Парт=ПолучитьПустоеЗначение("Документ.ПриходнаяНакладная");
// А это, что-бы заполнить хоть чем-нибудь измерение "Партия"
Регистр.ОстаткиТоваров.Склад = Склад;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолО;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 1;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОборотыТоваров.Склад = Склад;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолО;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 1;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
Подредактируем журнал "Накладные";
Изменим содержимое графы "Кол";
Добавим в выбранные значения графы Документ.РасходнаяНакладная.КолО;
Аналогично поступим и с графой "Сумма";
2.23 Расходная накладная. Продолжение.
Документ " Расходная накладная" создан! Давайте проверим его в работе. И посмотрим, как у нас будет списываться товар при разных способах.
Загружаем 1С:Предприятие;
Способ списания – FIFO;
Создаем Расходную накладную №1 от 08.10.2000;
Укажем какого-нибудь покупателя и его договор;
Укажем склад №3;
[Подбор] (Надо-же проверить);
Выберем кефир, всего его 40;
Он есть только в 1-ом сорте в количестве 40;
Пусть будет 1-ый сорт 22 штуки;
Выберем яблоки – их 200 кг;
Они есть в 1-ом сорте – 100 кг. и во 2-ом – 100 кг;
Сперва выберем 1-ый сорт – 55 кг.;
А затем снова яблоки, но уже 2-ой сорт – 55 кг.;
Закроем окно подбора;
[ОК]. Сохраним и проведем документ;
Смотрим движения документа;
Регистр "Взаиморасчеты" – ничего необычного;
Регистр "ОстаткиТоваров" – как и требовалось, в первую очередь товар списывался с более ранней накладной по ее цене прихода;
Регистр "ОборотыТоваров" – в соответствии со списываемыми партиями;
Метод FIFO – все в порядке;
Распроведем приходную накладную №1;
Установим в константе способ списания – LIFO;
Вернемся к накладной и проведем ее;
Смотрим движения;
И здесь все правильно;
Распроведем приходную накладную №1;
Установим в константе способ списания – По-среднему;
Вернемся к накладной и проведем ее;
Смотрим движения;
Никаких партий и суммы взяты с учетом средней цены остатка;
Все три основных способа списания реализованы правильно. (Есть еще способ учета "по-среднему с переоценками", он хорош тем, что при нем не накапливаются потерянные копейки как при обычном методе "по-среднему", но он сложен для реализации и встречается реже. Мы его не рассматриваем);
Попробуйте еще, для эксперимента, списать товара больше, чем есть на складе;
2.24 Накладная на перемещение.
Документ "Накладная на перемещение между складами" совместит в себе часть черт приходной и расходной накладных. Для простоты, в накладной на перемещение будет указана в качестве цены – цена поступления товара из справочника. Контрагента в ней не будет, следовательно не будет движений по регистру "Взаиморасчеты". Зато по каждому из оставшихся регистров движения будут двойные: по одному складу и по другому. Нумерация накладной будет совместная с расходными. И еще введем такой механизм, как ввод на основании. Он будет заключаться в возможности взяв приходную накладную, ее содержимым автоматически заполнить накладную на перемещение. Накладная будет располагаться в журнале накладных. Сведем все данные по документу а таблицу:
Идентификатор: НакладнаяНаПеремещение Журнал: Накладные Нумератор: Накладные Периодичность: Длина: Тип: Уникальность: Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?: нет |
Дополнение
СкладО
Склад отправитель
С.Склады
СкладП
Склад получатель
С.Склады
Дополнение
Создаем новый документ;
В окне свойств документа указываем его настройки и вводим реквизиты;
Нажимаем [Ввод на основании...];
Ставим галочку в колонке "Вводить на основании" напротив "ПриходнаяНакладная";
[ОК];
Форму документа сделаем аналогичной расходной накладной. Колонка "Цена" и поле ввода "НомерДок" недоступны;
Процедуры на элементы формы документа напишем по аналогии с приходной и расходной накладной. Учтем что мы будем использовать цену ЦенаП;
Добавим кнопку [Подбор] и пропишем для нее процедуры. Только Склад заменим в них на СкладО;
Теперь пропишем процедуру ввода на основании:
Процедура ВводНаОсновании(ДокОсн)
// предопределенная процедура. ДокОсн – ссылка на документ,
// на основании которого мы хотим ввести текущий
// если мы хотим, чтобы и в дальнейшем эти документы
// были между собой связаны, надо в документе, вводимом на
// основании завести реквизит типа документа основания
// и сохранять там эту ссылку
Если ДокОсн.Проведен()<>1 Тогда
// Если документ основание не проведен
// мы не можем ввести на его основании никакой документ
Предупреждение("Приходная накладная № "+Строка(ДокОсн.НомерДок) +"
| от "+Строка(ДокОсн.ДатаДок)+"
| не проведена!");
СтатусВозврата(0);
КонецЕсли;
ДатаДок=РабочаяДата();
// копируем реквизиты шапки
СкладО=ДокОсн.Склад;
СкладП="";
Пока ДокОсн.ПолучитьСтроку()=1 Цикл
// копируем содержимое строк
НоваяСтрока();
Товар=ДокОсн.Товар;
Сорт=ДокОсн.Сорт;
Кол=ДокОсн.Кол;
Ед=ДокОсн.Ед;
КолО=ДокОсн.КолО;
Цена=Товар.ЦенаП.Получить(ДатаДок);
Сумма=Окр(КолО*Цена,2,1);
КонецЦикла;
КонецПроцедуры
Процедуру проведения пишем по аналогии с расходной накладной:
Процедура ОбработкаПроведения()
РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");
Если СравнитьТА()=-1 Тогда
РегОст.ВременныйРасчет(1);
РассчитатьРегистрыНа(ТекущийДокумент());
КонецЕсли;
// Проверка на наличие на остатке
ВыбратьСтроки();
ФлагОтказа=0;
Пока (ПолучитьСтроку()>0) Цикл
Остат=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"Количество");
Если Остат<КолО Тогдаbr> Сообщить("Нет товара № "+СокрЛП(Товар.Код)+"/"
+СокрЛП(Сорт.Наименование)+" в колич. "
+КолО+" (имеется "+Остат+")");
ФлагОтказа=1;
КонецЕсли;
КонецЦикла;
Если ФлагОтказа=1 Тогда
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Если Константа.МетодСписания=Перечисление.МетодСписания.ФИФО Тогда
// Здесь будет записана методика списания по FIFO
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
КолСпис=КолО;
Запрос="";
ТекстЗапроса="";
Если ИтогиАктуальны()=0 Тогда
ТекстЗапроса="
|Период с ДатаДок по ДатаДок;";
КонецЕсли;
ТекстЗапроса=ТекстЗапроса+"
|РегСклад=Регистр.ОстаткиТоваров.Склад;
|РегТовар=Регистр.ОстаткиТоваров.Товар;
|РегСорт=Регистр.ОстаткиТоваров.Сорт;
|РегПартия=Регистр.ОстаткиТоваров.Партия;
|РегКолич=Регистр.ОстаткиТоваров.Количество;
|РегСумма=Регистр.ОстаткиТоваров.СуммаП;
| Группировка РегПартия Упорядочить по РегПартия.ДатаДок;
|Функция КолКонОст=КонОст(РегКолич);
|Функция СумКонОст=КонОст(РегСумма);
|Условие (РегСклад=СкладО);
|Условие (РегТовар=Товар);
|Условие (РегСорт=Сорт);";
Запрос=СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Документ не проведен");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Пока Запрос.Группировка("РегПартия",1)=1 Цикл
// Сортируем группировку по возрастанию
Если КолСпис=0 Тогда
Прервать;
КонецЕсли;
ПартияСписания=Запрос.РегПартия;
Если Запрос.КолКонОст>КолСпис Тогда
Списывать=КолСпис;
Стоимость=Окр((Запрос.СумКонОст/Запрос.КолКонОст)
*Списывать,2,1);
ИначеЕсли Запрос.КолКонОст=КолСпис Тогда
Списывать=КолСпис;
Стоимость=Запрос.СумКонОст;
ИначеЕсли Запрос.КолКонОст<КолСпис Тогдаbr> Списывать=Запрос.КолКонОст;
Стоимость=Запрос.СумКонОст;
КонецЕсли;
КолСпис=КолСпис-Списывать;
Регистр.ОстаткиТоваров.Склад = СкладО;
// по одному складу
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = ПартияСписания;
Регистр.ОстаткиТоваров.Количество = Списывать;
Регистр.ОстаткиТоваров.СуммаП = Стоимость;
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
// у нас движение внутреннее
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОстаткиТоваров.Склад = СкладП;
// по другому складу
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = ПартияСписания;
Регистр.ОстаткиТоваров.Количество = Списывать;
Регистр.ОстаткиТоваров.СуммаП = Стоимость;
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
Регистр.ОборотыТоваров.Склад = СкладО;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Списывать;
Регистр.ОборотыТоваров.СуммаУ = Стоимость;
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
Регистр.ОборотыТоваров.Склад = СкладП;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Списывать;
Регистр.ОборотыТоваров.СуммаУ = Стоимость;
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
КонецЦикла;
ИначеЕсли Константа.МетодСписания=Перечисление.МетодСписания.ЛИФО Тогда
// Здесь будет записана методика списания по LIFO
ТабЗн1=СоздатьОбъект("ТаблицаЗначений");
ТабЗн2=СоздатьОбъект("ТаблицаЗначений");
ТабЗн2.НоваяКолонка("Партия","Документ.ПриходнаяНакладная");
ТабЗн2.НоваяКолонка("КоличествоП","Число",14,2);
ТабЗн2.НоваяКолонка("СуммаП","Число",19,2);
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолВыб=КолО;
РегОст.УстановитьФильтр(СкладО,Товар,Сорт);
РегОст.ВыгрузитьИтоги(ТабЗн1,1,1);
ТабЗн1.Свернуть("4","5,6");
ТабЗн1.ВыбратьСтроки();
Пока ТабЗн1.ПолучитьСтроку()=1 Цикл
Прт=ТабЗн1.Партия;
Ост=ТабЗн1.Количество;
Сум=ТабЗн1.СуммаП;
Если Ост>0 Тогда // есть что проверять
ТабЗн2.НоваяСтрока();
ТабЗн2.Партия=Прт;
ТабЗн2.КоличествоП=Ост;
ТабЗн2.СуммаП=Сум;
КонецЕсли;
КонецЦикла;
ТабЗн1.Очистить();
ТабЗн2.Сортировать("1-",1);
// Способ сортировки по убывающей (-)
ТабЗн2.ВыбратьСтроки();
Пока ТабЗн2.ПолучитьСтроку()=1 Цикл
Ост=ТабЗн2.КоличествоП;
Сум=ТабЗн2.СуммаП;
ЦенаПП=Окр(Сум/Ост,2,1);
Парт=ТабЗн2.Партия;
Если КолВыб>Ост Тогда // Ост
Регистр.ОстаткиТоваров.Склад = СкладО;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = Ост;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОстаткиТоваров.Склад = СкладП;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = Ост;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*Ост,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Ост,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
Регистр.ОборотыТоваров.Склад = СкладО;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Ост;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
Регистр.ОборотыТоваров.Склад = СкладП;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = Ост;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*Ост,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
Иначе
Если КолВыб> 0 Тогда // КолВыб
Регистр.ОстаткиТоваров.Склад = СкладО;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолВыб;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолВыб,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОстаткиТоваров.Склад = СкладП;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолВыб;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолВыб,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
Регистр.ОборотыТоваров.Склад = СкладО;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолВыб;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
Регистр.ОборотыТоваров.Склад = СкладП;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолВыб;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенаПП*КолВыб,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КолВыб=КолВыб-Ост;
КонецЕсли;
КонецЕсли;
КонецЦикла;
ТабЗн2.УдалитьСтроки();
КонецЦикла;
ИначеЕсли
Константа.МетодСписания=Перечисление.МетодСписания.По_среднему Тогда
// Здесь будет записана методика списания по-среднему
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
КолОст=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"Количество");
СумОст=РегОст.СводныйОстаток(СкладО,Товар,Сорт,,"СуммаП");
ЦенОст=Окр(СумОст/КолОст,2,1);
Парт=ПолучитьПустоеЗначение("Документ.ПриходнаяНакладная");
Регистр.ОстаткиТоваров.Склад = СкладО;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолО;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();
Регистр.ОстаткиТоваров.Склад = СкладП;
Регистр.ОстаткиТоваров.Товар = Товар;
Регистр.ОстаткиТоваров.Сорт = Сорт;
Регистр.ОстаткиТоваров.Партия = Парт;
Регистр.ОстаткиТоваров.Количество = КолО;
Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);
Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);
Регистр.ОстаткиТоваров.ФлагДвижения = 2;
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.ДвижениеПриходВыполнить();
Регистр.ОборотыТоваров.Склад = СкладО;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолО;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
Регистр.ОборотыТоваров.Склад = СкладП;
Регистр.ОборотыТоваров.Товар = Товар;
Регистр.ОборотыТоваров.Сорт = Сорт;
Регистр.ОборотыТоваров.Количество = КолО;
Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);
Регистр.ОборотыТоваров.ФлагДвижения = 2;
Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОборотыТоваров.ДвижениеВыполнить();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Здесь мы переставили алгоритмы списания местами, в расходной накладной при списании по методу FIFO мы использовали алгоритм выгрузки регистра, а LIFO – запрос, то теперь наоборот, с соответствующими изменениями.
Внесем дополнения по аналогии с другими накладными в журнал "Накладные";
Войдем в окно редактирования документа "ПриходнаяНакладная";
[Ввод на основании...];
Может являться основанием для документа любого вида – Нет;
Сохраним конфигурацию;
Войдем в 1С:Предприятие;
Сделаем нашу расходную накладную не проведенной;
Установим способ списания – FIFO;
На основании приходной накладной №7 введем накладную на перемещение. Для этого установим в журнале курсор на нужном документе. Меню Действия команда "Ввести на основании";
Создалась уже почти заполненная накладная на перемещение №2 от 08.10.2000;
Укажем склад получатель – Склад №2;
Проведем накладную;
Посмотрим на движения. Хоть мы и указали как основание накладную №7, у нас списалось с более ранней накладной №6. Как написали алгоритм списания – так и получилось. Отсюда мораль: "Программа делает не то, что хочешь, а то, что напишешь!";
Глава 9
2.25 Оборотные ведомости.
Документом "Накладная на перемещение " мы завершили создание системы учета остатков на складах и товарооборота. Но учет не имеет смысла без отчетности. У нас уже есть отчеты, которые показывают состояние остатков и долгов на конкретную дату. Создадим два отчета: один нам покажет изменение долгов за какой-то период, а второй движение по складу товаров.
Создаем новый отчет "ОбороткаПоДолгам";
Добавим поле ввода ДатаН – тип Дата, формула ДатаН();
Добавим поле ввода ДатаК – тип Дата, формула ДатаК();
Пропишем процедуры в модуле формы:
Процедура ДатаН()
Если ДатаН>ДатаК Тогда
ДатаН=ДатаК;
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура ДатаК()
Если ДатаК<ДатаН Тогдаbr> ДатаК=ДатаН;
ИначеЕсли ДатаК>ПолучитьДатуТА() Тогда
ДатаК=ПолучитьДатуТА();
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура Сформировать()
Запрос=СоздатьОбъект("Запрос");
ТекстЗапроса="
|Период с ДатаН по ДатаК;
|Контр = Регистр.Взаиморасчеты.Контрагент;
|Догов = Регистр.Взаиморасчеты.Договор;
|Сумма = Регистр.Взаиморасчеты.Сумма;
|Флаг = Регистр.Взаиморасчеты.ФлагДвижения;
|Функция СуммаНачОст = НачОст(Сумма);
|Функция СуммаПриходТов = Приход(Сумма) когда(Флаг=1);
|Функция СуммаРасходТов = Расход(Сумма) когда(Флаг=2);
|Функция СуммаРасходДен = Расход(Сумма) когда(Флаг=3);
|Функция СуммаПриходДен = Приход(Сумма) когда(Флаг=4);
|Функция СуммаКонОст = КонОст(Сумма);
|Группировка Контр упорядочить по Контр.Код;
|Группировка Догов;";
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Таблица");
ИтНачОст=Запрос.СуммаНачОст;
ИтПрихТов=Запрос.СуммаПриходТов;
ИтРасхДен=Запрос.СуммаРасходДен;
ИтРасхТов=Запрос.СуммаРасходТов;
ИтПрихДен=Запрос.СуммаПриходДен;
ИтКонОст=Запрос.СуммаКонОст;
// для итогов перед началом прохода по группировкам получаем
// значения функций для всей выборки сразу
Таб.ВывестиСекцию("Шапка");
Пока Запрос.Группировка(1)=1 Цикл
Контра=Запрос.Контр;
НачОст=Запрос.СуммаНачОст;
ПрихТов=Запрос.СуммаПриходТов;
РасхДен=Запрос.СуммаРасходДен;
РасхТов=Запрос.СуммаРасходТов;
ПрихДен=Запрос.СуммаПриходДен;
КонОст=Запрос.СуммаКонОст;
Если Контра.ЭтоГруппа()=1 Тогда
Таб.ВывестиСекцию("Группа");
Иначе
Таб.ВывестиСекцию("Контра");
Пока Запрос.Группировка(2)=1 Цикл
Дог=Запрос.Догов;
НачОст=Запрос.СуммаНачОст;
ПрихТов=Запрос.СуммаПриходТов;
РасхДен=Запрос.СуммаРасходДен;
РасхТов=Запрос.СуммаРасходТов;
ПрихДен=Запрос.СуммаПриходДен;
КонОст=Запрос.СуммаКонОст;
Таб.ВывестиСекцию("Дог");
КонецЦикла;
КонецЕсли;
КонецЦикла;
Таб.ВывестиСекцию("Итого");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Создадим шаблон печатной формы;
Сохраним конфигурацию;
Создаем новый отчет "ОбороткаПоСкладу";
Добавим поле ввода ДатаН – тип Дата, формула ДатаН();
Добавим поле ввода ДатаК – тип Дата, формула ДатаК();
Добавим поле ввода Склад – тип С.Склады;
Пропишем процедуры в модуле формы:
//-----------------------------------------------
Процедура ДатаН()
Если ДатаН>ДатаК Тогда
ДатаН=ДатаК;
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура ДатаК()
Если ДатаК<ДатаН Тогдаbr> ДатаК=ДатаН;
ИначеЕсли ДатаК>ПолучитьДатуТА() Тогда
ДатаК=ПолучитьДатуТА();
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура Сформировать()
Если Склад.Выбран()=0 Тогда
Сообщить("Не выбран склад");
Возврат;
КонецЕсли;
Запрос=СоздатьОбъект("Запрос");
ТекстЗапроса="
|Период с ДатаН по ДатаК;
|Скл = Регистр.ОстаткиТоваров.Склад;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Сорт = Регистр.ОстаткиТоваров.Сорт;
|Количество = Регистр.ОстаткиТоваров.Количество;
|ФлагДвижения = Регистр.ОстаткиТоваров.ФлагДвижения;
|Функция КолНачОстС = НачОст(Количество);
|Функция КолПриходК = Приход(Количество) когда(ФлагДвижения=1);
|Функция КолПриходВ = Приход(Количество) когда(ФлагДвижения=2);
|Функция КолРасходВ = Расход(Количество) когда(ФлагДвижения=2);
|Функция КолРасходК = Расход(Количество) когда(ФлагДвижения=1);
|Функция КолКонОстС = КонОст(Количество);
| Группировка Товар упорядочить по Товар.Код;
|Группировка Сорт;
|Условие(Скл=Склад);";
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
Таб.ВывестиСекцию("Шапка");
ИтНачОстС = Запрос.КолНачОстС;
ИтПриходК = Запрос.КолПриходК;
ИтПриходВ = Запрос.КолПриходВ;
ИтРасходВ = Запрос.КолРасходВ;
ИтРасходК = Запрос.КолРасходК;
ИтКонОстС = Запрос.КолКонОстС;
Пока Запрос.Группировка("Товар")=1 Цикл
ТТов=Запрос.Товар;
НачОстС = Запрос.КолНачОстС;
ПриходК = Запрос.КолПриходК;
ПриходВ = Запрос.КолПриходВ;
РасходВ = Запрос.КолРасходВ;
РасходК = Запрос.КолРасходК;
КонОстС = Запрос.КолКонОстС;
Если ТТов.ЭтоГруппа()=1 Тогда
Тов=СокрЛП(ТТов.Наименование);
Таб.ВывестиСекцию("Группа");
Иначе
Тов=СокрЛП(ТТов.Код)+" ("+СокрЛП(ТТов.Наименование)+")";
НачОстС = Запрос.КолНачОстС;
ПриходК = Запрос.КолПриходК;
ПриходВ = Запрос.КолПриходВ;
РасходВ = Запрос.КолРасходВ;
РасходК = Запрос.КолРасходК;
КонОстС = Запрос.КолКонОстС;
Таб.ВывестиСекцию("Товар");
Пока Запрос.Группировка("Сорт")=1 Цикл
Срт=Запрос.Сорт;
НачОстС = Запрос.КолНачОстС;
ПриходК = Запрос.КолПриходК;
ПриходВ = Запрос.КолПриходВ;
РасходВ = Запрос.КолРасходВ;
РасходК = Запрос.КолРасходК;
КонОстС = Запрос.КолКонОстС;
Таб.ВывестиСекцию("Сорт");
КонецЦикла;
КонецЕсли;
КонецЦикла;
Таб.ВывестиСекцию("Итого");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Во многом модуль этого отчета похож на предыдущий.
Создадим шаблон печатной формы;
Сохраним изменения в конфигурации;
Загрузим 1С:Предприятие;
Создадим несколько новых документов, проведем старые и посмотрим, что выдадут нам наши отчеты;
2.26 Отчет по прибыли с товара.
В регистре "ОстаткиТовара" мы хранили такую информацию, как сумма поступления и сумма реализации. Создадим отчет, показывающий прибыль, которую мы получили в результате нашей хозяйственной деятельности.
Создаем новый отчет "Прибыль";
Добавим поле ввода ДатаН – тип Дата, формула ДатаН();
Добавим поле ввода ДатаК – тип Дата, формула ДатаК();
Добавим поле ввода Склад – тип С.Склады;
Добавим кнопку [Х]. Пропишем в поле Формула свойств кнопки Склад="", этой кнопкой мы будем очищать поле "Склад";
Пропишем процедуры в модуле формы:
Процедура ДатаН()
Если ДатаН>ДатаК Тогда
ДатаН=ДатаК;
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура ДатаК()
Если ДатаК<ДатаН Тогдаbr> ДатаК=ДатаН;
ИначеЕсли ДатаК>ПолучитьДатуТА() Тогда
ДатаК=ПолучитьДатуТА();
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура Сформировать()
Запрос=СоздатьОбъект("Запрос");
ТекстЗапроса="
|Период с ДатаН по ДатаК;
|Скл = Регистр.ОстаткиТоваров.Склад;
|Товар = Регистр.ОстаткиТоваров.Товар;
|Сорт = Регистр.ОстаткиТоваров.Сорт;
|Количество = Регистр.ОстаткиТоваров.Количество;
|СуммаП = Регистр.ОстаткиТоваров.СуммаП;
|СуммаД = Регистр.ОстаткиТоваров.СуммаД;
|Ф = Регистр.ОстаткиТоваров.ФлагДвижения;
|Функция КоличРасходС = Расход(Количество) когда(Ф=1);
|Функция СуммаПРасход = Расход(СуммаП) когда(Ф=1);
|Функция СуммаДРасход = Расход(СуммаД) когда(Ф=1);
|Группировка Товар упорядочить по Товар.Код без групп;
|Группировка Сорт упорядочить по Сорт.Код;";
// Мы не хотим в запросе получать группы товара (для примера)
СклТекст="По всем складам";
Если Склад.Выбран()=1 Тогда
СклТекст="По складу: "+СокрЛП(Склад.Наименование);
ТекстЗапроса=ТекстЗапроса+"
|Условие(Скл=Склад);";
КонецЕсли;
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
ИтКолРасх = Запрос.КоличРасходС;
ИтСумПРас = Запрос.СуммаПРасход;
ИтСумДРас = Запрос.СуммаДРасход;
ИтПрибыль = ИтСумДРас-ИтСумПРас;
Таб.ВывестиСекцию("Шапка");
Пока Запрос.Группировка("Товар")=1 Цикл
ТТов=Запрос.Товар;
Тов=СокрЛП(ТТов.Код)+" ("+СокрЛП(ТТов.Наименование)+")";
КолРасх = Запрос.КоличРасходС;
СумПРас = Запрос.СуммаПРасход;
СумДРас = Запрос.СуммаДРасход;
Прибыль = СумДРас-СумПРас;
Таб.ВывестиСекцию("Товар");
Пока Запрос.Группировка("Сорт")=1 Цикл
Срт=Запрос.Сорт;
КолРасх = Запрос.КоличРасходС;
СумПРас = Запрос.СуммаПРасход;
СумДРас = Запрос.СуммаДРасход;
Прибыль = СумДРас-СумПРас;
Таб.ВывестиСекцию("Сорт");
КонецЦикла;
КонецЦикла;
Таб.ВывестиСекцию("Итого");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Создадим шаблон печатной формы;
2. 27 Отчет по обороту товара.
Сформируем отчет по товарообороту. Для него мы возьмем данные из регистра "ОборотыТоваров".
Создаем новый отчет "ТоварооборотПоСкладу";
Добавим поле ввода ДатаН – тип Дата, формула ДатаН();
Добавим поле ввода ДатаК – тип Дата, формула ДатаК();
Добавим поле ввода Склад – тип С.Склады;
Добавим кнопку [Х]. Пропишем в поле Формула свойств кнопки Склад="", этой кнопкой мы будем очищать поле "Склад";
Пропишем процедуры в модуле формы:
//-----------------------------------------------
Процедура ДатаН()
Если ДатаН>ДатаК Тогда
ДатаН=ДатаК;
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура ДатаК()
Если ДатаК<ДатаН Тогдаbr> ДатаК=ДатаН;
ИначеЕсли ДатаК>ПолучитьДатуТА() Тогда
ДатаК=ПолучитьДатуТА();
КонецЕсли;
КонецПроцедуры
//-----------------------------------------------
Процедура Сформировать()
Запрос=СоздатьОбъект("Запрос");
ТекстЗапроса="
|Период с ДатаН по ДатаК;
|Скл = Регистр.ОборотыТоваров.Склад;
|Тов = Регистр.ОборотыТоваров.Товар;
|Срт = Регистр.ОборотыТоваров.Сорт;
|Кол = Регистр.ОборотыТоваров.Количество;
|Сум = Регистр.ОборотыТоваров.СуммаУ;
|Функция КолСум = Сумма(Кол);
|Функция СумСум = Сумма(Сум);
|Группировка Тов упорядочить по Тов.Код без групп;
|Группировка Срт упорядочить по Сорт.Код;";
СклТекст="По всем складам";
Если Склад.Выбран()=1 Тогда
СклТекст="По складу: "+СокрЛП(Склад.Наименование);
ТекстЗапроса=ТекстЗапроса+"
|Условие(Скл=Склад);";
КонецЕсли;
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
ИтКолСум = Запрос.КолСум;
ИтСумСум = Запрос.СумСум;
Таб.ВывестиСекцию("Шапка");
Пока Запрос.Группировка("Товар")=1 Цикл
ТТов=Запрос.Товар;
Тов=СокрЛП(ТТов.Код)+" ("+СокрЛП(ТТов.Наименование)+")";
КолСум = Запрос.КолСум;
СумСум = Запрос.СумСум;
Таб.ВывестиСекцию("Товар");
Пока Запрос.Группировка("Сорт")=1 Цикл
Срт=Запрос.Сорт;
КолСум = Запрос.КолСум;
СумСум = Запрос.СумСум;
Таб.ВывестиСекцию("Сорт");
КонецЦикла;
КонецЦикла;
Таб.ВывестиСекцию("Итого");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Создадим шаблон печатной формы;
Теперь мы можем загрузить 1С:Предприятие и посмотреть, что нам выдадут наши отчеты;
Глава 10
2.28 Новые наборы прав.
Мы все это время работали с одним набором прав. Права мы себе присвоили самые неограниченные, но при реальной работе это недопустимо. Разным пользователям, в зависимости от их служебных обязанностей, должен быть разный уровень допуска к данным. Одним можно все, другим - почти все, третьим – только просмотр результатов, а четвертых вообще к машине допускать нельзя. Разговор пойдет о первых трех категориях пользователей.
Пользователь первой категории у нас уже создан.
Пользователя второй категории нам предстоит создать. Пусть это будет кладовщик. Он может вводить и проводить накладные и просматривать отчеты по остаткам и оборотам на складе. Снимать с проведения документы он не будет иметь права.
Список прав кладовщика:
- Справочник - Идентификатор "Номенклатура" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Единицы" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Склады" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Контрагенты" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Договора" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Сорт" - Чтение Да - Остальное Нет - Документ - Идентификатор "ПриходнаяНакладная" - Чтение Да - ВводНового Да - ПометкаНаУдаление Да - Корректировка Да - Выбор Да - ПроведениеДокумента Да - Остальное Нет - Документ - Идентификатор "РасходнаяНакладная" - Чтение Да - ВводНового Да - ПометкаНаУдаление Да - Корректировка Да - Выбор Да - ПроведениеДокумента Да - Остальное Нет - Документ - Чтение Да - ВводНового Да - ПометкаНаУдаление Да - Корректировка Да - Выбор Да - ПроведениеДокумента Да - Остальное Нет - Журнал - Идентификатор "Накладные" - Чтение Да - Отчет - Идентификатор "ОстаткиНаСкладе" - Использование Да - Отчет - Идентификатор "ОбороткаПоСкладу" - Использование Да - Отчет - Идентификатор "ТоварооборотПоСкладу" - Использование Да |
Переходим к окну с деревом метаданных;
Переключаемся на закладку "Права";
Создаем новый набор прав "Кладовщик";
Меню Действия команда "Редактировать";
Появилось окно "Кладовщик – Редактор пользовательских прав" с деревом метаданных;
Найдем в этом окне справочник "Номенклатура";
Вызовем его свойства;
Появилось окно с набором доступов;
Поставим галочку у пункта "Чтение", а остальные пункты оставим не помеченными;
Аналогично расставим доступы для остальных объектов метаданных;
Закроем окно редактирования прав;
Мы вернулись в окно со списком наборов прав. Давайте теперь определим, что можно такому пользователю как начальник. Сам он заполнять справочники не будет. Документы он тоже формировать не захочет. Начальники любят отчетность. Значит он у нас попадает в третью группу пользователей. Мы ему даем право просмотра любой информации, без возможности ее изменить.
- Константа - Идентификатор "ЕдИзмПоУмолчанию" - Чтение Да - Корректировка Нет - Константа - Идентификатор "ПроцентНаценки" - Чтение Да - Корректировка Нет - Константа - Идентификатор "СортПоУмолчанию" - Чтение Да - Корректировка Нет - Константа - Идентификатор "МетодСписания" - Чтение Да - Корректировка Нет - Справочник - Идентификатор "Номенклатура" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Единицы" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Склады" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Контрагенты" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Договора" - Чтение Да - Остальное Нет - Справочник - Идентификатор "Сорт" - Чтение Да - Остальное Нет - Документ - Идентификатор "ПриходДенег" - Чтение Да - Выбор Да - Остальное Нет - Документ - Идентификатор "ВыплатаДенег" - Чтение Да - Выбор Да - Остальное Нет - Документ - Идентификатор "ИзменениеЦен" - Чтение Да - Выбор Да - Остальное Нет - Документ - Идентификатор "ПриходнаяНакладная" - Чтение Да - Выбор Да - Остальное Нет - Документ - Идентификатор "РасходнаяНакладная" - Чтение Да - Выбор Да - Остальное Нет - Документ - Идентификатор "НакладнаяНаПеремещение" - Чтение Да - Выбор Да - Остальное Нет - Журнал - Идентификатор "ДвижениеДенег" - Чтение Да - Журнал - Идентификатор "ИзменениеЦен" - Чтение Да - Журнал - Идентификатор "Накладные" - Чтение Да - Отчет - Идентификатор "Взаиморасчеты" - Использование Да - Отчет - Идентификатор "ОстаткиНаСкладе" - Использование Да - Отчет - Идентификатор "ОбороткаПоДолгам" - Использование Да - Отчет - Идентификатор "ОбороткаПоСкладу" - Использование Да - Отчет - Идентификатор "Прибыль" - Использование Да - Отчет - Идентификатор "ТоварооборотПоСкладу" - Использование Да |
Создаем набор прав "Начальник";
Устанавливаем ему его права;
2.29 Новые интерфейсы.
Раздав права надо позаботиться и о соответствующих интерфейсах. Если пользователю что не положено, он этого и видеть не должен. Сперва создадим интерфейс кладовщика, как более простой.
Заходим на закладку "Интерфейсы";
Меню Действия команда "Новый интерфейс";
Название "Кладовщик". Отключим меню "Операции";
Меню Действия команда "Редактировать";
Выбираем Редактировать... Меню;
Появилось окно "Кладовщик – Редактор меню";
Вернемся к окну со списком интерфейсов;
Откроем окно с редактированием меню Администратора;
Выделим ветку "Справочники" и скопируем ее в буфер;
Перейдем к окну Кладовщика и вставим из буфера ветку "Справочники";
Поступим также и с остальными ветками меню;
А теперь открывая по очереди ветки меню кладовщика удалим лишние пункты;
Интерфейс кладовщика готов;
Разберемся с интерфейсом начальника. Его интерфейс будет очень похож на интерфейс Администратора. Будет только отсутствовать ветка "Документы". Сделаем для шефа подчиненный интерфейс на основе интерфейса Администратора.
Входим в окно со списком интерфейсов;
Ставим курсор на интерфейс Администратора;
Меню Действия команда "Новый подчиненный интерфейс";
Название "Начальник". Отключим меню "Операции". И будем использовать его при отключенной авторизации;
Откроем новый интерфейс для редактирования;
Мы видим список пунктов меню Администратора. Отключим лишние;
Теперь остается создать пару пользователей с новыми правами и интерфейсами и посмотреть, как это все выглядит.
Бухгалтерия
Введение
Дополнение
Сумма
Число 10.2
3, +
Дополнение
Создаем форму документа. Поля АвторДокумента и Курс сделаем недоступными. В полях валюта и ДатаКурса в формуле укажем процедуру Валюта().
Разместим реквизиты формы документа в более-менее приемлемом виде.
В модуле формы напишем:
Перем СтВалюта;
Перем СтДатаКурса;
Перем СтКурс;
//Переменные для пересчета суммы при изменении валюты документа
//==========================================================
Процедура ВводНового()
АвторДокумента=СокрЛП(ИмяПользователя());
ФирмаДокумента=Константа.ОснФирма;
Валюта=Константа.ОснВалюта;
ДатаКурса=ДатаДок;
Курс=1;
// Заполняем значения по умолчанию
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
КонецПроцедуры
//==========================================================
Процедура ПриОткрытии()
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
ПриЗаписиПерепроводить(1);
// При записи изменений перепроводить обязательно
КонецПроцедуры
//==========================================================
Процедура Валюта()
КурсС=СтКурс;
КратС=СтВалюта.Кратность;
КурсН=Валюта.Курс.Получить(ДатаКурса);
КратН=Валюта.Кратность;
Коэфф=Окр((КурсС*КратН)/(КурсН*КратС),6,1);
// Переводим в валюту документа
Курс=КурсН;
Сумма=Окр(Сумма*Коэфф,2,1);
// Пересчитываем сумму
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
КонецПроцедуры
Перейдем к модулю документа. Учет мы будем вести в базовой валюте. Здесь мы напишем самый наипростейший вариант модуля проведения. В данном случае нам надо только перевести сумму с одного счета на другой одной проводкой. Напишем процедуру проведения:
Процедура ОбработкаПроведения()
КурсД=Курс;
КратД=Валюта.Кратность;
КурсУ=Константа.ОснВалюта.Курс.Получить(ДатаДок);
КратУ=Константа.ОснВалюта.Кратность;
Коэфф=Окр((КурсД*КратУ)/(КурсУ*КратД),6,1); // переводим в валюту документа
СуммаО=Окр(Сумма*Коэфф,2,1);
// Пересчитали сумму документа в сумму операции в базовую валюту
ПривязыватьСтроку(0);
// Следующая за этой командой новая проводка к строке документа не
// привязывается
Операция.НоваяПроводка();
// Создаем проводку (простую) по операции
Операция.Дебет.Счет = СчетПоКоду("68.1",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("19.3",ПланыСчетов.Наш);
// Указали корреспонденцию проводки
Операция.Сумма = СуммаО;
// Сумма проводки
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Учет НДС за приобретенные комплектующие";
Операция.НомерЖурнала = " ";
// Дополнительные сведения по проводке
Операция.Содержание = "Учет НДС";
Операция.СуммаОперации = СуммаО;
Операция.Автор = СокрЛП(ИмяПользователя());
// Дополнительные сведения по операции
Операция.Записать();
КонецПроцедуры
2.32 Работа с документом УчетНДС.
Документ создан. Давайте его проверим. Входим в 1С:Предприятие и создаем новый документ "Учет НДС" на сумму 1000 тугриков (для примера), затем меняем валюту на рубли и получаем 22.77 рубля (при курсе 22.77 руб. за 1000 тугриков) все сходится, вернем тугрики. Сохраним и проведем документ. Смотрим журнал операций (Меню Действия команда "Перейти в журнал операций"). Сумма операции 22.77 (при сумме документа 1000) – верно. Проверяем проводку – тоже все верно. Документ написан правильно. Удалим этот документ, чтобы не мешал.
2.33 Документ ПриходнаяНакладная.
По приходной накладной мы будем получать комплектующие от поставщиков. Проводка по этому документу сложнее (Д 10.2 – К 60, Д 19.3 – К 60). В данном документе нас интересует следующее: кто поставил нам комплектующие, на какой склад мы их приняли, что конкретно пришло, в каком количестве, по какой цене без НДС, на какую сумму. Сведем все в таблицу:
Идентификатор: ПриходнаяНакладная Журнал: ПриходныеНакладные Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет |
|
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да |
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет |
Создавать операцию: Всегда Редактировать операцию: нет |
|
Дополнение
Поставщик
С.Контрагенты
Склад
С.Склады
Дополнение
Отредактируем журнал ПриходныеНакладные. Добавим в него две графы – Кол из реквизита таблицы Кол, и Сумма из реквизита СуммаСНДС. Настроим форму журнала.
Перейдем к форме документа. Создаем ее. Поля АвторДокумента и Курс делаем недоступными. В полях ввода Валюта и ДатаКурса пишем формулу Валюта(). Поля табличной части СуммаБНДС, СуммаНДС, СуммаСНДС делаем недоступными. В поле Товар пишем формулу Товар(), в поле Кол – Кол(), в поле ЦенаБНДС – ЦенаБНДС(), в поле ЦенаСНДС – ЦенаСНДС(). Под таблицей добавим текст с формулой для вычисления суммы по колонке Итог("Кол"), Итог("СуммаБНДС"), Итог("СуммаБНДС"). В модуле формы документа пишем:
Перем СтВалюта;
Перем СтДатаКурса;
Перем СтКурс;
//==========================================================
Процедура ВводНового()
АвторДокумента=СокрЛП(ИмяПользователя());
ФирмаДокумента=Константа.ОснФирма;
Валюта=Константа.ОснВалюта;
ДатаКурса=ДатаДок;
Курс=1;
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
Поставщик = Константа.ОснПоставщик;
КонецПроцедуры
//==========================================================
Процедура ПриОткрытии()
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
ПриЗаписиПерепроводить(1);
КонецПроцедуры
//==========================================================
Процедура Валюта()
// При смене валюты, либо даты курса
КурсС=СтКурс;
КратС=СтВалюта.Кратность;
КурсН=Валюта.Курс.Получить(ДатаКурса);
КратН=Валюта.Кратность;
Коэфф=Окр((КурсС*КратН)/(КурсН*КратС),6,1); // переводим в валюту документа
Курс=КурсН;
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
// Обходим строки
ЦенаБНДС=Окр(ЦенаБНДС*Коэфф,2,1);
ЦенаСНДС=Окр(ЦенаСНДС*Коэфф,2,1);
СуммаБНДС=Окр(ЦенаБНДС*Кол,2,1);
СуммаСНДС=Окр(ЦенаСНДС*Кол,2,1);
СуммаНДС=СуммаСНДС-СуммаБНДС;
КонецЦикла;
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
КонецПроцедуры
//==========================================================
Процедура Товар()
// Изменили товар, пересчитаем цену с НДС
ЦенаСНДС=Окр(ЦенаБНДС*(1+(Товар.НДС.Значение/100)),2,1);
СуммаСНДС=Окр(ЦенаСНДС*Кол,2,1);
СуммаНДС=СуммаСНДС-СуммаБНДС;
КонецПроцедуры
//==========================================================
Процедура Кол()
СуммаБНДС=Окр(ЦенаБНДС*Кол,2,1);
СуммаСНДС=Окр(ЦенаСНДС*Кол,2,1);
СуммаНДС=СуммаСНДС-СуммаБНДС;
КонецПроцедуры
//==========================================================
Процедура ЦенаБНДС()
ЦенаСНДС=Окр(ЦенаБНДС*(1+(Товар.НДС.Значение/100)),2,1);
// Определим цену с НДС по цене без НДС
СуммаБНДС=Окр(ЦенаБНДС*Кол,2,1);
СуммаСНДС=Окр(ЦенаСНДС*Кол,2,1);
СуммаНДС=СуммаСНДС-СуммаБНДС;
КонецПроцедуры
//==========================================================
Процедура ЦенаСНДС()
ЦенаБНДС=Окр(ЦенаСНДС*(1-(Товар.НДС.ОбрЗначение/100)),2,1);
// Определим цену без НДС по цене с НДС
СуммаБНДС=Окр(ЦенаБНДС*Кол,2,1);
СуммаСНДС=Окр(ЦенаСНДС*Кол,2,1);
СуммаНДС=СуммаСНДС-СуммаБНДС;
КонецПроцедуры
Теперь переходим к модулю документа. В этом документе наша операция будет уже посложней, в одной операции будет объединено несколько проводок, причем одна проводка будет относиться ко всему документу целиком, а остальные будут формироваться по строкам документа. Пишем следующую процедуру
Процедура ОбработкаПроведения()
Если Склад.Выбран()=0 Тогда
// Если склад не указан
Сообщить("Документ Приходная накладная №"+НомерДок+" от "+ДатаДок+"
|не проведен.
|Не выбран склад получатель");
// Делаем сообщение
НеПроводитьДокумент();
// Указываем, что документ проводить не надо
Возврат;
// Выходим из процедуры
КонецЕсли;
Если Поставщик.Выбран()=0 Тогда
Сообщить("Документ Приходная накладная №"+НомерДок+" от "+ДатаДок+"
|не проведен.
|Не выбран поставщик");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
КурсД=Курс;
КратД=Валюта.Кратность;
КурсУ=Константа.ОснВалюта.Курс.Получить(ДатаДок);
КратУ=Константа.ОснВалюта.Кратность;
Коэфф=Окр((КурсД*КратУ)/(КурсУ*КратД),6,1);
// Переводим в валюту документа
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
// Обходим строки
ПривязыватьСтроку(НомерСтроки);
// Здесь мы хотим указать какая строка документа вызвала эту проводку
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("10.2",ПланыСчетов.Наш);
Операция.Дебет.МестоХранения = Склад;
Операция.Дебет.Комплектующее = Товар;
Операция.Дебет.ПриходнаяНакладная = ТекущийДокумент();
Операция.Кредит.Счет = СчетПоКоду("60",ПланыСчетов.Наш);
Операция.Кредит.Контрагент = Поставщик;
Операция.Кредит.ПриходнаяНакладная = ТекущийДокумент();
Операция.Количество = Кол;
Операция.Сумма = Окр(СуммаБНДС*Коэфф,2,1);
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Поступление комплектующих";
Операция.НомерЖурнала = "6";
КонецЦикла;
ПривязыватьСтроку(0);
// Эта проводка по всему документу вцелом
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("19.3",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("60",ПланыСчетов.Наш);
Операция.Кредит.Контрагент = Поставщик;
Операция.Кредит.ПриходнаяНакладная = ТекущийДокумент();
Операция.Сумма = Окр(Итог("СуммаНДС")*Коэфф,2,1);
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Учет НДС по поступ. комплектующим";
Операция.НомерЖурнала = "6";
Операция.Содержание = "Поступление комплектующих";
Операция.СуммаОперации = Окр(Итог("СуммаСНДС")*Коэфф,2,1);
Операция.Автор = АвторДокумента;
Операция.Записать();
КонецПроцедуры
Теперь, когда создан документ "Приходная накладная", нам надо внести соответствующую поправку в Субконто ПриходнаяНакладная. Укажем в этом Субконто тип как Д.ПриходнаяНакладная.
2.34 Работа с документом ПриходнаяНакладная.
Документ "Приходная накладная" создан, в интерфейс внесен сам документ и его журнал. Давайте попробуем поработать с этим документом. Войдем в 1С:Предприятие и создадим Приходную накладную №1 от 02.01.2001.
Цены попытаемся вводить как с НДС, так и без НДС. Попробуем менять валюту. И наконец, проведем этот документ и посмотрим на получившуюся операцию и проводки. Создана одна операция на сумму 270 рублей и четыре проводки, три по дебету 10-ого счета на сумму 75, 100 и 50 рублей, и одна по дебету 19-ого счета на сумму 45 рублей. Документ попробуем проводить с разной валютой.
Используем теперь документ "Учет НДС" для списания с налогов суммы уплаченного поставщику НДС за купленные нами комплектующие. Вводим УчетНДС №1 от 03.01.2001. Сумма – 45 рублей. Проводим. Смотрим на операцию и проводку. Посмотрим как действует журнал проводок (меню Действия, команда "Перейти в журнал проводок"). Попробуем разделить по журналам нашим флажком. Все работает.
Глава 7
2.37 Документ НарядНаСборку.
Этим документом мы будем запускать в производство очередную партию комплектующих. В наряде будет указано с какого склада брать заготовки, кто из работников будет заниматься сборкой и, главное, какие изделия и в каком количестве должны быть сделаны. Количество и ассортимент комплектующих мы будем определять по справочнику Комплектация.
Проводка документа (Д 20 – К 10.2). Документ должен будет списать со склада некоторое количество комплектующих, при этом списание должно идти по методу FIFO, в первую очередь из более ранних накладных.
Документ будет помещен в специальный журнал.
Идентификатор: НарядНаСборку Журнал: НарядыНаСборку Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет |
|
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да |
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет |
Создавать операцию: Всегда Редактировать операцию: нет |
|
Дополнение
Склад
С.Склады
Сборщик
С.Сотрудники
Дополнение
В журнал добавим графу "Сборщик". Создаем форму документа.
Поля Валюта, ДатаКурса, Курс удаляем. Поле АвторДокумента делаем недоступным. Добавляем кнопку [Заявка] с формулой Заявка(), по этой кнопке мы будем распечатывать перечень входящих в изделия комплектующих, с указанием общего количества.
В табличную часть добавим поле текст с функцией Ост(Склад,Изделие), эта колонка будет показывать, для какого количества изделий хватит комплектующих (но, эта функция будет показывать только возможное количество, она, разумеется, не учитывает возможность участия комплектующего в разных изделиях). В поле табличной части Кол добавляем процедуру Кол(), эта процедура будет проверять, не превышает ли указанное количество изделий возможное, исходя из запасов на складе. Еще раз подобную проверку мы будем делать в модуле проведения.
В модуле формы документа пишем:
Процедура ВводНового()
АвторДокумента=СокрЛП(ИмяПользователя());
ФирмаДокумента=Константа.ОснФирма;
Валюта=Константа.ОснВалюта;
ДатаКурса=ДатаДок;
Курс=1;
КонецПроцедуры
//==========================================================
Процедура ПриОткрытии()
ПриЗаписиПерепроводить(1);
КонецПроцедуры
//==========================================================
Процедура Заявка()
// Печать спецификации
ТабЗн=СоздатьОбъект("ТаблицаЗначений");
ТабЗн.НоваяКолонка("Ком","Справочник.Комплектующие");
ТабЗн.НоваяКолонка("Кол","Число",12,0);
СпрКом=СоздатьОбъект("Справочник.Комплектация");
// Подчиненный справочнику Изделия справочник Комплектация
ВыбратьСтроки();
// Обходим строки документа
Пока ПолучитьСтроку()=1 Цикл
СпрКом.ИспользоватьВладельца(Изделие);
// Выбираем комплектующие по изделию
СпрКом.ВыбратьЭлементы();
// Обходим справочник с составом комплектов
Пока СпрКом.ПолучитьЭлемент()=1 Цикл
ТабЗн.НоваяСтрока();
ТабЗн.Ком=СпрКом.ТекущийЭлемент().Комплектующее;
// Это мы определили, что входит в комплект
ТабЗн.Кол=Кол;
// И сколько
КонецЦикла;
СпрКом.ИспользоватьВладельца("");
КонецЦикла;
СпрКом="";
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
Таб.ВывестиСекцию("Шапка");
ТабЗн.Свернуть("1","2");
// Суммируем строки с одинаковыми комплектующими
ТабЗн.Сортировать("1");
ТабЗн.ВыбратьСтроки();
Стр=1;
Пока ТабЗн.ПолучитьСтроку()=1 Цикл
Комп=ТабЗн.Ком;
НазвРодителя=СокрЛП(Комп.Родитель.Наименование);
Поз1=Найти(НазвРодителя,"(");
Поз2=Найти(НазвРодителя,")");
ГОСТ=Сред(НазвРодителя,Поз1+1,Поз2-Поз1-1);
Ком=СокрЛП(Комп.Наименование)+" "+ГОСТ;
Колич=ТабЗн.Кол;
Таб.ВывестиСекцию("Строка");
Стр=Стр+1;
КонецЦикла;
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
//==========================================================
Функция Ост(Скл,Изд)
// Функция с двумя параметрами на входе: Склад и Изделие
СпЗн=СоздатьОбъект("СписокЗначений");
СпрКом=СоздатьОбъект("Справочник.Комплектация");
БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги");
БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш);
БухИтоги.ИспользоватьРазделительУчета(ФирмаДокумента);
СпрКом.ИспользоватьВладельца(Изд);
СпрКом.ВыбратьЭлементы();
// Обходим все комплектующие, входящие в изделие
Пока СпрКом.ПолучитьЭлемент()=1 Цикл
СКом=СпрКом.ТекущийЭлемент();
Ком=СКом.Комплектующее;
БухИтоги.ИспользоватьСубконто(ВидыСубконто.МестоХранения,Скл,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Комплектующее,Ком,2);
// Отбираем по указанному складу и текущей комплектующей
БухИтоги.ВыполнитьЗапрос(,ДатаДок,"10.2");
КолКом=БухИтоги.СКД(3);
// Выясняем, сколько штук этих комплектующих еще есть на складе
СпЗн.ДобавитьЗначение(КолКом);
// Добавляем в список
КонецЦикла;
СпрКом="";
ИОст=0;
// Ищем минимальное значение в списке
Для ЧЦ=1 По СпЗн.РазмерСписка() Цикл
ТТТ="";
Если ЧЦ=1 Тогда
КолСп=СпЗн.ПолучитьЗначение(ЧЦ,ТТТ);
ИОст=КолСп;
Иначе
КолСп=СпЗн.ПолучитьЗначение(ЧЦ,ТТТ);
Если ИОст>КолСп Тогда
ИОст=КолСп;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат(ИОст);
// Выдаем это минимальное значение
КонецФункции
//==========================================================
Процедура Кол()
ОстКомпл=Ост(Склад,Изделие);
// Выясняем остаток на складе
Если Кол>ОстКомпл Тогда
// Если запросили больше
Кол=ОстКомпл;
// Даем сколько есть
КонецЕсли;
КонецПроцедуры
Теперь пропишем процедуру проведения. Здесь у нас будет формирование движения партий, но не по строкам документа, а по комплектующим, определяемым через эти строки. Проводки будут только одного типа (Д 20 – К 10.2). Здесь же будет проверка, не запрашиваем ли мы комплектующих больше, чем есть на складе.
Процедура ОбработкаПроведения()
Если Склад.Выбран()=0 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+"
|от "+ДатаДок+" не проведен.
|Не выбран склад заготовок");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Если Сборщик.Выбран()=0 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+"
|от "+ДатаДок+" не проведен.
|Не указан сборщик");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
// Это были обычные проверки
ТабЗн=СоздатьОбъект("ТаблицаЗначений");
ТабЗн.НоваяКолонка("Ком","Справочник.Комплектующие");
ТабЗн.НоваяКолонка("Кол","Число",12,0);
СпрКом=СоздатьОбъект("Справочник.Комплектация");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
СпрКом.ИспользоватьВладельца(Изделие);
СпрКом.ВыбратьЭлементы();
Пока СпрКом.ПолучитьЭлемент()=1 Цикл
ТабЗн.НоваяСтрока();
ТабЗн.Ком=СпрКом.ТекущийЭлемент().Комплектующее;
ТабЗн.Кол=Кол;
КонецЦикла;
СпрКом.ИспользоватьВладельца("");
КонецЦикла;
БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги");
БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш);
БухИтоги.ИспользоватьРазделительУчета(ФирмаДокумента);
ФлагОтказа=0;
ТабЗн.Свернуть("1","2");
ТабЗн.ВыбратьСтроки();
Пока ТабЗн.ПолучитьСтроку()=1 Цикл
Ком=ТабЗн.Ком;
Колич=ТабЗн.Кол;
БухИтоги.ИспользоватьСубконто(ВидыСубконто.МестоХранения,Склад,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Комплектующее,Ком,2);
БухИтоги.ВыполнитьЗапрос(,ДатаДок,"10.2");
КолКом=БухИтоги.СКД(3);
Если Колич>КолКом Тогда
ФлагОтказа=1;
Сообщить(Строка(Ком));
КонецЕсли;
КонецЦикла;
// Если посмотреть модуль документа, это похоже на процедуру Заявка()
Если ФлагОтказа=1 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+"
|от "+ДатаДок+" не проведен.
|Заказ по вышеперечисленным позициям
|превышает остаток на складе");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
// Отказ от проведения по причине нехватки комплектующих
ТабЗн.УдалитьСтроки();
ТабЗн="";
ТабПар=СоздатьОбъект("ТаблицаЗначений");
ТабПар.НоваяКолонка("Док","Документ.ПриходнаяНакладная");
ТабПар.НоваяКолонка("Кол","Число",10,0);
ТабПар.НоваяКолонка("Сум","Число",14,2);
СуммаОпер=0;
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл // По Изделию
// Обходим строки
НС=НомерСтроки;
Изд=Изделие;
СпрКом.ИспользоватьВладельца(Изделие);
СпрКом.ВыбратьЭлементы();
Пока СпрКом.ПолучитьЭлемент()=1 Цикл // По Комплектующей
// Обходим комплектующие
Колич=Кол;
Ком=СпрКом.ТекущийЭлемент().Комплектующее;
БухИтоги.ИспользоватьСубконто(ВидыСубконто.МестоХранения,Склад,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Комплектующее,Ком,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная,,1);
БухИтоги.ВыполнитьЗапрос(,ДатаДок,"10.2");
ТабПар.УдалитьСтроки();
БухИтоги.ВыбратьСубконто(3);
// Выбираем только третье!!! субконто
Пока БухИтоги.ПолучитьСубконто(3)=1 Цикл
// Определяем партии
ДокП=БухИтоги.Субконто(3);
КолП=БухИтоги.СКД(3);
СумП=БухИтоги.СКД(1);
ТабПар.НоваяСтрока();
ТабПар.Док=ДокП;
ТабПар.Кол=КолП;
ТабПар.Сум=СумП;
КонецЦикла;
ТабПар.Сортировать("1+");
ТабПар.ВыбратьСтроки();
Пока ТабПар.ПолучитьСтроку()=1 Цикл // По Партии
// Обходим партии
ДокП=ТабПар.Док;
КолП=ТабПар.Кол;
СумП=ТабПар.Сум;
Если Колич>КолП Тогда
ПривязыватьСтроку(НС);
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("20",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("10.2",ПланыСчетов.Наш);
Операция.Дебет.ВидЗатрат = Перечисление.ВидыЗатрат.НаКомплектующие;
Операция.Дебет.Изделие = Изделие;
Операция.Дебет.НарядНаКомплектацию = ТекущийДокумент();
Операция.Кредит.МестоХранения = Склад;
Операция.Кредит.Комплектующее = Ком;
Операция.Кредит.ПриходнаяНакладная = ДокП;
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Передача комплектующих на сборку";
Операция.НомерЖурнала = "10";
Операция.Сумма = СумП;
Операция.Количество = КолП;
Колич=Колич-КолП;
СуммаОпер=СуммаОпер+СумП;
// Накапливаем сумму операции по каждой проводке
Иначе
СумО=Окр(Колич*(СумП/КолП),2,1);
// Определяем сумму остатка через цену партии
ПривязыватьСтроку(НС);
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("20",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("10.2",ПланыСчетов.Наш);
Операция.Дебет.ВидЗатрат = Перечисление.ВидыЗатрат.НаКомплектующие;
Операция.Дебет.Изделие = Изделие;
Операция.Дебет.НарядНаКомплектацию = ТекущийДокумент();
Операция.Кредит.МестоХранения = Склад;
Операция.Кредит.Комплектующее = Ком;
Операция.Кредит.ПриходнаяНакладная = ДокП;
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Передача комплектующих на сборку";
Операция.НомерЖурнала = "10";
Операция.Сумма = СумО;
Операция.Количество = Колич;
СуммаОпер=СуммаОпер+СумО;
// Накапливаем сумму операции по каждой проводке
Прервать;
// Все кончилось, больше партии по этому комплектующему обходить незачем
КонецЕсли;
КонецЦикла; // По Партии
КонецЦикла; // По Комплектующей
КонецЦикла; // По Изделию
Операция.Содержание = "Запуск производства";
Операция.СуммаОперации = СуммаОпер;
Операция.Автор = АвторДокумента;
Операция.Записать();
КонецПроцедуры
Вроде бы все. Но этот механизм не будет правильно списывать партии в том случае, если в документе будут разные изделия, содержащие одинаковые комплектующие. Это показывает разницу в алгоритмическом подходе при использовании компонент Оперативный учет и Бухгалтерский учет. В Оперативном учете можно проводя строки документа все время отслеживать меняющиеся остатки, а в Бухгалтерском учете операция формируется в самом конце.
Например, в изделии А (10 шт.) есть комплектующая К, и в изделии Б (10 шт.) есть комплектующая К. Суммарно изделие К должно быть списано из партии 1 и из партии 2 по 10 штук, но этот механизм дважды спишет К из партии 1. А это неправильно. Перепишем эту процедуру заново:
Процедура ОбработкаПроведения()
Если Склад.Выбран()=0 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+" от "+ДатаДок+"
|не проведен.
|Не выбран склад заготовок");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
Если Сборщик.Выбран()=0 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+" от "+ДатаДок+"
|не проведен.
|Не указан сборщик");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
ТабЗн=СоздатьОбъект("ТаблицаЗначений");
ТабЗн.НоваяКолонка("Ком","Справочник.Комплектующие");
ТабЗн.НоваяКолонка("Кол","Число",12,0);
СпрКом=СоздатьОбъект("Справочник.Комплектация");
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
СпрКом.ИспользоватьВладельца(Изделие);
СпрКом.ВыбратьЭлементы();
Пока СпрКом.ПолучитьЭлемент()=1 Цикл
ТабЗн.НоваяСтрока();
ТабЗн.Ком=СпрКом.ТекущийЭлемент().Комплектующее;
ТабЗн.Кол=Кол;
КонецЦикла;
СпрКом.ИспользоватьВладельца("");
КонецЦикла;
БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги");
БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш);
БухИтоги.ИспользоватьРазделительУчета(ФирмаДокумента);
ФлагОтказа=0;
ТабЗн.Свернуть("1","2");
ТабЗн.ВыбратьСтроки();
Пока ТабЗн.ПолучитьСтроку()=1 Цикл
Ком=ТабЗн.Ком;
Колич=ТабЗн.Кол;
БухИтоги.ИспользоватьСубконто(ВидыСубконто.МестоХранения,Склад,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Комплектующее,Ком,2);
БухИтоги.ВыполнитьЗапрос(,ДатаДок,"10.2");
КолКом=БухИтоги.СКД(3);
Если Колич>КолКом Тогда
ФлагОтказа=1;
Сообщить(Строка(Ком));
КонецЕсли;
КонецЦикла;
Если ФлагОтказа=1 Тогда
Сообщить("Документ Наряд на сборку №"+НомерДок+" от "+ДатаДок+"
|не проведен.
|Заказ по вышеперечисленным позициям
|превышает остаток на складе");
НеПроводитьДокумент();
Возврат;
КонецЕсли;
// Без изменений
ТабКом=СоздатьОбъект("ТаблицаЗначений");
ТабКом.НоваяКолонка("Ком","Справочник.Комплектующие");
ТабКом.НоваяКолонка("Док","Документ.ПриходнаяНакладная");
ТабКом.НоваяКолонка("Кол","Число",10,0);
ТабКом.НоваяКолонка("Сум","Число",14,2);
// В этой таблице мы будем хранить список комплектующих в разрезе партий
// в количестве, достаточном для списания
ТабЗн.Сортировать("1+");
ТабЗн.ВыбратьСтроки();
Пока ТабЗн.ПолучитьСтроку()=1 Цикл
КомП=ТабЗн.Ком;
КолКом=ТабЗн.Кол;
БухИтоги.ИспользоватьСубконто(ВидыСубконто.МестоХранения,Склад,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Комплектующее,КомП,2);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная,,1);
БухИтоги.ВыполнитьЗапрос(,ДатаДок,"10.2");
БухИтоги.ВыбратьСубконто(3);
Пока БухИтоги.ПолучитьСубконто(3)=1 Цикл
ДокП=БухИтоги.Субконто(3);
КолП=БухИтоги.СКД(3);
СумП=БухИтоги.СКД(1);
Если КолКом>0 Тогда
// Заполняем таблицу по комплектующим-партиям
ТабКом.НоваяСтрока();
ТабКом.Ком=КомП;
ТабКом.Док=ДокП;
ТабКом.Кол=КолП;
ТабКом.Сум=СумП;
КолКом=КолКом-КолП;
Иначе
Прервать;
// Чтобы не выбирать лишних партий
КонецЕсли;
КонецЦикла;
КонецЦикла;
ТабЗн.УдалитьСтроки();
ТабЗн="";
ТабКом.Сортировать("1+,2+");
СуммаОпер=0;
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл // По Изделию
НС=НомерСтроки;
Изд=Изделие;
СпрКом.ИспользоватьВладельца(Изделие);
СпрКом.ВыбратьЭлементы();
Пока СпрКом.ПолучитьЭлемент()=1 Цикл // По Комплектующей
Колич=Кол;
КомТ=СпрКом.ТекущийЭлемент().Комплектующее;
ТабКом.ВыбратьСтроки();
Пока ТабКом.ПолучитьСтроку()=1 Цикл // По Партии
// Выбираем партии из динамической таблицы!
КомП=ТабКом.Ком;
Если КомП<>КомТ Тогда
Продолжить;
// Запрашиваемая комплектующая не соответствует строке в таблицу, идем дальше
КонецЕсли;
ДокП=ТабКом.Док;
КолП=ТабКом.Кол;
Если КолП=0 Тогда
// Партия уже опустошена, пропускаем
Продолжить;
КонецЕсли;
СумП=ТабКом.Сум;
СтрП=ТабКом.НомерСтроки;
Если Колич>КолП Тогда
ПривязыватьСтроку(НС);
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("20",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("10.2",ПланыСчетов.Наш);
Операция.Дебет.ВидЗатрат = Перечисление.ВидыЗатрат.НаКомплектующие;
Операция.Дебет.Изделие = Изделие;
Операция.Дебет.НарядНаКомплектацию = ТекущийДокумент();
Операция.Кредит.МестоХранения = Склад;
Операция.Кредит.Комплектующее = КомП;
Операция.Кредит.ПриходнаяНакладная = ДокП;
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = " Передача комплектующих на сборку";
Операция.НомерЖурнала = "10";
Операция.Сумма = СумП;
Операция.Количество = КолП;
Колич=Колич-КолП;
СуммаОпер=СуммаОпер+СумП;
ТабКом.УстановитьЗначение(СтрП,"Кол",0);
ТабКом.УстановитьЗначение(СтрП,"Сум",0);
// Опустошаем партию полностью
Иначе
СумО=Окр(Колич*(СумП/КолП),2,1);
ПривязыватьСтроку(НС);
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("20",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("10.2",ПланыСчетов.Наш);
Операция.Дебет.ВидЗатрат = Перечисление.ВидыЗатрат.НаКомплектующие;
Операция.Дебет.Изделие = Изделие;
Операция.Дебет.НарядНаКомплектацию = ТекущийДокумент();
Операция.Кредит.МестоХранения = Склад;
Операция.Кредит.Комплектующее = КомП;
Операция.Кредит.ПриходнаяНакладная = ДокП;
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Передача комплектующих на сборку";
Операция.НомерЖурнала = "10";
Операция.Сумма = СумО;
Операция.Количество = Колич;
СуммаОпер=СуммаОпер+СумО;
ТабКом.УстановитьЗначение(СтрП,"Кол",КолП-Колич);
ТабКом.УстановитьЗначение(СтрП,"Сум",СумП-СумО);
// Опустошаем партию частично и переходим к следующей комплектующей
Прервать;
КонецЕсли;
КонецЦикла; // По Партии
КонецЦикла; // По Комплектующей
КонецЦикла; // По Изделию
Операция.Содержание = "Запуск производства";
Операция.СуммаОперации = СуммаОпер;
Операция.Автор = АвторДокумента;
Операция.Записать();
КонецПроцедуры
Новый вариант хотя и сложнее, но работает правильно. И даже быстрее, так как обращений к Бухгалтерским итогам будет меньше или столько же, ведь они вынесены за цикл по изделиям.
Проверим работу нашего документа с разными наборами данных.
2.40 Документ ПриходныйОрдер.
Товар отгружен, пора получить за него денежки. Деньги мы будем получать с покупателя наличными в кассу по Приходному ордеру. Проводка в документе будет всего одна (Д 50.1 – К 62). Списывать долг с конкретного покупателя мы будем в разрезе конкретной накладной на отгруз. Причем, если сумма в ордере больше непогашенного остатка по указанной накладной, то мы раскидаем остаток прихода денег по остальным непогашенным накладным клиента, а если накладная не указана, то спишем долг по самой ранней накладной. Этот документ будет очень похож на Расходный ордер, поэтому просто скопируем его и внесем небольшие изменения.
Сведем данные по документу в таблицу:
Идентификатор: ПриходныйОрдер Журнал: Кассовые Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет |
|
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да |
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет |
Создавать операцию: Всегда Редактировать операцию: нет |
|
Дополнение
Плательщик
от кого
С.Контрагенты
Основание
за что платит
Д.РасходнаяНакладная
Сумма
сколько
Число 12.2
3, +
Дополнение
В журнале "Кассовые" добавим в графу таблицы – Сумма из реквизита документа "ПриходныйОрдер" Сумма.
Перейдем к редактированию формы документа. Сделаем все аналогично с Расходным ордером. Модуль формы напишите сами, он тоже аналогичен.
Модуль проведения тоже аналогичен... Пишите сами для тренировки. Только учтите, что 62-ой счет пассивный и сальдо у него есть только по кредиту!
2.41 Документ Ведомость.
Ну вот, наконец, мы перешли к самому главному документу нашей конфигурации – Ведомости на зарплату. По сему наиважнейшему документу мы должны выплатить работникам трудовую копейку. Этот документ будет содержать список сотрудников и суммы к выплате, кроме того, в документе будет особая кнопка для занесения в ведомость всех сотрудников, по которым есть что платить. Сделаем в этом документе возможность редактировать операции.
Сведем все в таблицу:
Идентификатор: Ведомость Журнал: Ведомости Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет |
|||||
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да |
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет |
||||
Создавать операцию: Всегда Редактировать операцию: да |
|||||
Дополнение
Сотрудник
С.Сотрудники
Сумма
Число 10.2
+, И
Документ в отдельном журнале.
Приведем форму журнала в вид, нравящийся нам.
Отредактируем форму документа.
Поля АвторДокумента и Курс делаем недоступными. В поля Валюта, ДатаКурса добавляем формулу Валюта(). Вставляем кнопку [Заполнить] с формулой Заполнить(). Вставляем поле текст с формулой Итог("Сумма") – для итога по колонке.
В модуле формы документа пишем:
Перем СтВалюта;
Перем СтДатаКурса;
Перем СтКурс;
//==========================================================
Процедура ВводНового()
АвторДокумента=СокрЛП(ИмяПользователя());
ФирмаДокумента=Константа.ОснФирма;
Валюта=Константа.ОснВалюта;
ДатаКурса=ДатаДок;
Курс=1;
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
КонецПроцедуры
//==========================================================
Процедура ПриОткрытии()
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
ПриЗаписиПерепроводить(1);
КонецПроцедуры
//==========================================================
Процедура Валюта()
КурсС=СтКурс;
КратС=СтВалюта.Кратность;
КурсН=Валюта.Курс.Получить(ДатаКурса);
КратН=Валюта.Кратность;
Коэфф=Окр((КурсС*КратН)/(КурсН*КратС),6,1);
// переводим в валюту документа
Курс=КурсН;
ВыбратьСтроки();
Пока ПолучитьСтроку()=1 Цикл
Сумма=Окр(Сумма*Коэфф,2,1);
КонецЦикла;
СтВалюта=Валюта;
СтДатаКурса=ДатаКурса;
СтКурс=Курс;
КонецПроцедуры
//==========================================================
Процедура Заполнить()
КурсД=Курс;
КратД=Валюта.Кратность;
КурсУ=Константа.ОснВалюта.Курс.Получить(ДатаДок);
КратУ=Константа.ОснВалюта.Кратность;
Коэфф=Окр((КурсД*КратУ)/(КурсУ*КратД),6,1); // переводим в валюту документа
УдалитьСтроки();
// Очищаем табличную часть документа
БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги");
БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш);
БухИтоги.ИспользоватьРазделительУчета(ФирмаДокумента);
БухИтоги.ИспользоватьСубконто(ВидыСубконто.Сотрудник,,1);
БухИтоги.ВыполнитьЗапрос(,ТекущаяДата(),"70");
БухИтоги.ВыбратьСубконто(1);
Пока БухИтоги.ПолучитьСубконто(1)=1 Цикл
Сотр=БухИтоги.Субконто(1);
ИОст=БухИтоги.СКК(1);
НоваяСтрока();
// Заполняем новыми строками
Сотрудник=Сотр;
Сумма=Окр(ИОст*Коэфф,2,1);
КонецЦикла;
КонецПроцедуры
Напишем модуль проведения документа. Он очень простой.
Процедура ОбработкаПроведения()
КурсД=Курс;
КратД=Валюта.Кратность;
КурсУ=Константа.ОснВалюта.Курс.Получить(ДатаДок);
КратУ=Константа.ОснВалюта.Кратность;
Коэфф=Окр((КурсД*КратУ)/(КурсУ*КратД),6,1);
// переводим в валюту документа
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
Операция.НоваяПроводка();
Операция.Дебет.Счет = СчетПоКоду("70",ПланыСчетов.Наш);
Операция.Кредит.Счет = СчетПоКоду("50.1",ПланыСчетов.Наш);
Операция.Дебет.Сотрудник = Сотрудник;
Операция.Сумма = Окр(Сумма*Коэфф,2,1);
Операция.Фирма = ФирмаДокумента;
Операция.Комментарий = "Выплата зарплаты из кассы";
Операция.НомерЖурнала = "1";
КонецЦикла;
Операция.Содержание = "Выплата зарплаты";
Операция.СуммаОперации = Окр(Итог("Сумма")*Коэфф,2,1);
Операция.Автор = АвторДокумента;
Операция.Записать();
КонецПроцедуры
Как видите, все просто и коротко. Проверьте работоспособность документа в 1С:Предприятии. И попробуйте поредактировать операцию, создаваемую документом.
Глава 8
2.42 Отчет по остаткам на складе готовой продукции.
В принципе, конфигурация создана. Осталось только добавить пару отчетиков. Один отчет – Счет60 у нас уже есть. Создадим теперь отчет по остаткам на складе.
Вводим новый отчет "ОстаткиГотовойПродукции".
В модуль формы пишем:
Процедура ПриОткрытии()
ДатО = РабочаяДата();
КонецПроцедуры
//==========================================================
Процедура Сформировать()
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("Таблица");
Ит = СоздатьОбъект("БухгалтерскиеИтоги");
Ит.ИспользоватьПланСчетов(ПланыСчетов.Наш);
Ит.ИспользоватьРазделительУчета(Константа.ОснФирма);
Скл="По всем складам";
Суб=1;
Если ВСклад.Выбран()=1 Тогда
Ит.ИспользоватьСубконто(ВидыСубконто.МестоХранения,ВСклад,2);
Скл="По складу: "+СокрЛП(Строка(ВСклад));
Суб=2;
КонецЕсли;
Ит.ИспользоватьСубконто(ВидыСубконто.Изделие,,1);
Ит.ВыполнитьЗапрос(,ДатО,"40");
Таб.ВывестиСекцию("Шапка");
ИтКол=0;
ИтСумС=0;
ИтСумР=0;
ИтСумН=0;
Ит.ВыбратьСубконто(Суб);
Пока Ит.ПолучитьСубконто(Суб)=1 Цикл
Изд=Ит.Субконто(Суб);
Цен=Изд.Цена.Получить(ДатО);
Кол=Ит.СКД(3);
СумС=Ит.СКД(1);
СумР=Окр(Кол*Цен,2,1);
СумН=Окр(СумР*(1+Изд.НДС.Значение/100),2,1);
ИтКол=ИтКол+Кол;
ИтСумС=ИтСумС+СумС;
ИтСумР=ИтСумР+СумР;
ИтСумН=ИтСумН+СумН;
Таб.ВывестиСекцию("Строка");
КонецЦикла;
Таб.ВывестиСекцию("Подвал");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(2);
Таб.Показать("Сформировать","");
КонецПроцедуры
Делаем шаблон печатной формы
2.43 Отчет по покупателям.
Создадим теперь отчет по 62-ому счету - "Покупатели". В поле ДатН пишем формулу Дат("Н"), а в поле ДатК – Дат("К"). В модуль формы:
Процедура Сформировать()
Запрос=СоздатьОбъект("Запрос");
// Создаем запрос по базе данных
ТекстЗапроса="
|Период с ДатН по ДатК;
|Пок = Операция.Субконто.Контрагент;
|Сум = Операция.Сумма;
|Сч = Операция.Счет;
|Функция СумСНК = СНК(Сум) когда (Сч=СчетПоКоду(""62""));
|Функция СумСНД = СНД(Сум) когда (Сч=СчетПоКоду(""62""));
|Функция СумКО = КО(Сум) когда (Сч=СчетПоКоду(""62""));
// Нас интересуют кредитовые
|Функция СумДО = ДО(Сум) когда (Сч=СчетПоКоду(""62""));
// и дебетовые обороты
|Функция СумСКК = СКК(Сум) когда (Сч=СчетПоКоду(""62""));
|Функция СумСКД = СКД(Сум) когда (Сч=СчетПоКоду(""62""));
|Условие (Сч=СчетПоКоду(""62""));
// Другие чтоб не лезли... Если не поставить - в отчет
// Поставщики попадут с нулями
|Группировка Пок упорядочить по Пок.Наименование без Групп;";
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
ИтНачК=0;
ИтНачД=0;
ИтИзмК=0;
ИтИзмД=0;
ИтКонК=0;
ИтКонД=0;
// Это переменные для итога
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
Таб.ВывестиСекцию("Шапка");
Пока Запрос.Группировка(1)=1 Цикл
Клн=Запрос.Пок;
НачК=Запрос.СумСНК;
НачД=Запрос.СумСНД;
ИзмК=Запрос.СумКО;
ИзмД=Запрос.СумДО;
КонК=Запрос.СумСКК;
КонД=Запрос.СумСКД;
// Получаем разные сальдо и обороты...
ИтНачК=ИтНачК+НачК;
ИтНачД=ИтНачД+НачД;
ИтИзмК=ИтИзмК+ИзмК;
ИтКонД=ИтКонД+КонД;
ИтКонК=ИтКонК+КонК;
ИтИзмД=ИтИзмД+ИзмД;
// Складываем для окончательного итога
Таб.ВывестиСекцию("Строка");
КонецЦикла;
Таб.ВывестиСекцию("Подвал");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
//==========================================================
Процедура Дат(Тип)
// Процедура с переменной
Если Тип="Н" Тогда
Если ДатН > ДатК Тогда
ДатН=ДатК;
КонецЕсли;
ИначеЕсли Тип="К" Тогда
Если ДатК < ДатН Тогда
ДатК=ДатН;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
//==========================================================
ДатК=ТекущаяДата();
ДатН=НачМесяца(ДатК);
В этом отчете мы воспользовались не привычным нам уже объектом БухгалтерскиеИтоги, а объектом Запрос. С ним мы активно работали в первой методичке.
Создаем шаблон печатной формы
Проверяем работу отчета.
2.44 Новые счета в плане счетов.
Ну, вроде и все, фирма "Magic Inc" автоматизирована. И тут некий клиент узнает, что Бегемот умеет еще и починять примусы. Этот клиент приносит пару примусов и просит их отремонтировать. Что должен сделать бухгалтер. Ну, во-первых завести счет 002 – "Товарно-материальные ценности, принятые на ответственное хранение", счет 23 – "Вспомогательные производства" и счет 71 – "Расчеты с подотчетными лицами". Заведем их в нашу конфигурацию. Эти счета субсчетов иметь не будут.
Входим в 1С:Предприятие!!!
Открываем план счетов;
Добавляем новый счет 23, активный, субконто ВидЗатрат;
Добавляем новый счет 71, активно-пассивный, субконто Сотрудник;
Добавляем счет 002, активный, забалансовый;
Если мы приглядимся к списку счетов, то увидим – счета введенные в Конфигураторе имеют в пиктограмме красную галочку, а введенные в режиме Предприятия – нет.
А тем временем Бегемот, посланный в магазин за запчастями, приносит на обрывке бумаги: Необходимо провести это все через бухгалтерию.
Операция №1
Д 002 – 200 руб. Приняты в ремонт 2 примуса.
Операция №2
Д 71 К 50 – 100 руб. Выдано Бегемоту под отчет.
Операция №3
Д 10 К 71 – 71.67 руб. Приобретены Бегемотом запчасти
Д 19.3 К 71 – 14.33 руб. НДС за приобретенные запчасти.
Д 50 К 71 – 14.00 руб. Возвращен Бегемотом остаток из подотчетных сумм.
Операция №4
Д 23 К 10 – 71.67 руб. Запчасти переданы в производство
Операция №5
Д 23 К 70 – 3 руб. Бегемоту за работу
Операция №6
Д 90 К 23 – 74.67 руб. Реализованы услуги по себестоимости
Д 90 К 99 - 25.33 руб. Прибыль
Д 90 К 68 – 20 руб. НДС за оказанные услуги
Д 62 К 90 – 120 руб. На заказчика зачислен долг
Операция №7
Д 50 К 62 – 120 руб. Получены деньги
К 002 – 200 руб. Возвращены примусы
Операция №8
Д 68.1 К 19.3 – 14.37 руб. Зачтен НДС за запчасти.
Операция №9
Д 70 К 50 – 3 руб. Выплата Бегемоту зарплаты за починку примуса.
Все вроде замечательно. Но бухгалтер Коровьев отбывает в долгую творческую командировку, руководить хором песни и пляски народов крайнего Юго-Запада. А примусов на починку обещали еще поднести. Бухгалтер может создать кучу корректных проводок и установить в свойствах флаг всегда проверять по ним новые проводки операций и сделать ряд типовых операций, чтобы легче и проще было вводить однотипные операции, но это совсем другая история...
2.45 Совсем другая история.
Эта глава напрямую не относится к программированию, но для полноты картины, думается, будет не вредной.
Корректные проводки – это особый системный списочек проводок, которые главбух фирмы считает правильными (корректными). И ежели мы в настройках параметров системы (меню "Сервис", команда "Параметры"), на закладке "Операция" поставим галочку на настройке "Проверять проводки при записи операции", то при записи операции вводимой вручную будет выполняться контроль проводок с использованием списка корректных проводок (это я содрал из хелпа в 1С).
Теперь, поставив этот флажек, зайдем в журнал операций и посохраняем наши ручные операции еще раз. При наличии проводок по незабалансовым счетам программа нас будет спрашивать, а не добавить ли текущую корреспонденцию к списочку корректных проводок? Давайте согласимся, и после пересохранения последней ручной операции посмотрим на список корректных проводок (меню "Операции" комманда "Корректные проводки"). Этот список можно использовать в программе через объект "КорректныеПроводки". Но мы здесь этим заниматься не будем.
Вместе с господином Коровьевым переходим к типовым операциям. Входим в меню "Операции", комманда "Типовые операции". Появился пустой еще пока список. Добавим в него первую запись "Выдача денег под отчет" (эта операция простая и поэтому на ее примере будет проще разобраться). Входим в режим редактирования типовой операции (меню "Действия", комманда "Редактировать"). Появилось окно конструктора типовой операции.
Через меню "Действие" командой "Новая проводка" введем строку для создания проводки;
Сразу укажем фирму – "Magic Inc";
Журнал – 1 (кредит 50 счета);
Укажем счет дебета – 70, Субконто 1 по этому счету – сотрудники фирмы, здесь мы можем сразу указать Бегемота, а можем и не указывать. Если мы его укажем, то мы можем установить флаг активизации для этого поля – Пропускать, и тогда при вводе опреации на основании типовой, нам не будет предлагаться выбрать сотрудника;
Укажем счет кредита – 50.1;
Перейдем к сумме проводки. Здесь мы воспользуемся формулой. Установив курсор на поле Сумма в строке проводки перейдем к полю Формула (при этом поле суммы проводки будет обведено синей рамкой). В поле формула пишем: СуммаОперации. Таким образом при вводе суммы операции сумма проводки будет рассчитываться автоматически.
Если у нас много проводок, мы можем распределить между ними сумму операции по каким либо правилам. Таким же способом можно рассчитывать поле Валютной суммы.
Ну и заполним поле комментария к проводке.
Осталось сохранить внесенные настройки – Меню "Действия" команда "Сохранить".
Теперь можно проверить, как это все будет работать. Установив курсор в списке типовых операций на нашей операции и через меню "Действия" командой "Ввести операцию" создадим операцию на основе типовой. При заполнении поля суммы операции поле суммы проводки заполнилось автоматически, что нам и требовал
Зарплата
Введение
Компонента Расчет в системе 1С:Предприятие предназначена для реализации сложных периодических расчетов. Обычно она используется для расчета зарплаты.
Дополнительно
Здесь:
Д – отбор движений;
И – отбор итогов;
+ - не отрицательный;
Движения по регистру будут следующие:
Приход – приход к нам товара (общей суммой) либо денег;
Расход – отгруз нами товара (общей суммой) либо выплата денег.
Переходим к конструированию регистра.
Создаем новый регистр;
Идентификатор - "Взаиморасчеты", Комментарий – "регистр взаиморасчетов с контрагентами", Измерения, ресурсы, реквизиты – по таблице, Тип регистра – остатки, быстрая обработка движений – по желанию;
2.13 Первый документ. Приход денег.
У нас есть контрагенты и договора с ними, у нас есть место (регистр), где мы можем хранить информацию по взаиморасчетам с ними. Теперь нам нужен документ, который позволит вводить эти взаиморасчеты. Первым нашим документом будет документ "Приход денег".
В любом документе в 1С есть два поля, присутствующих всегда. Это "ДатаДок" – дата документа и "НомерДок" – номер документа. 1С позволяет завести еще сколько надо полей, которые будут присутствовать во всех документах. Это "Общие реквизиты" документа. Заведем один такой общий реквизит – "Комментарий" текстового типа длиной не более 100 символов. Назначение его ясно из названия.
Входим в ветвь "Документы" дерева метаданных;
Устанавливаем курсор на раздел "Общие реквизиты";
Вводим новый общий реквизит;
Идентификатор – "Комментарий", тип – Строка, длина – 100;
Обговорим теперь структуру нашего документа "Приход денег". Кроме полей с датой, номером и комментарием нам, разумеется, понадобится указание – кто нам эти деньги платит? – "Контрагент", на каком основании он платит нам эти деньги? – "Договор", сколько денег он нам платит? – "Сумма". Типы полей "Контрагент" и "Договор" - соответствующие справочники. Поле "Сумма" будет у нас Число 9.2. Создадим этот документ.
Вводим новый документ;
Идентификатор – "ПриходДенег", Синоним – "Приход денег", Комментарий – "приход денег от контрагента";
Документ будет проводиться – да, при записи документ будет перепроводиться – да;
Здесь необходимо дать пояснение, что такое проведение документа. Проведение документа – это внесение соответствующих изменений в механизмы хранения данных (в регистры, планы счетов, журналы расчетов). Документ, у которого стоит указание на возможность проведения, может находиться в трех состояниях – не существует (наиболее частое), записан – данные сохранены, проведен – данные сохранены и учтены в механизме хранения данных (если этот механизм не указан, документ все равно считается проведенным) – т. е. совершил какое-то движение в учете.
Документ будет принадлежать журналу – да, Создать новый журнал – "ДвижениеДенег";
Журнал – список документов определенного/определенных видов. Имеет экранную форму.
И документ и журнал вставим в экранное меню;
Открылось окно свойств документа;
В перечень реквизитов шапки занесем наши реквизиты – "Контрагент", "Договор", "Сумма". Табличной (многострочной) части в этом документе нет;
Нумератор – не назначен, Периодичность – год;
Периодичность – это как часто будет появляться документ с номером 1.
Автоматическая нумерация строк – нет (у нас строк не будет);
Оперативный учет – ДА;
Этим мы покажем, что движение осуществляется по регистрам.
Создадим форму документа;
Вставим поле с текстом, где мы укажем название документа;
Расставим элементы экранной формы документа поудобнее;
В свойствах поля договор на закладке "Дополнительно" в поле "связан с" пишем "Контрагент";
Справочник "Договора" у нас подчиненный, и мы в форме документа указываем, что договора мы будем брать, принадлежащие ранее указанному контрагенту.
Мы желаем, чтобы при выборе другого контрагента, поле договор очищалось;
В свойствах поля ввода "Контрагент" на закладке "Дополнительно" пишем формулу Контрагент();
В модуле формы пишем следующую процедуру:
Перем СтКонтрагент;
// Это мы добавили переменную, область действия которой
// весь модуль формы документа
//-----------------------------------------------
Процедура ПриОткрытии()
// Это предопределенная процедура, запускается при возникновении
// события – открытие формы документа
// Она сформировалась автоматически, как мы указали в визарде создания
// документов
ПриЗаписиПерепроводить(1);
// Это означает, что если мы проведенный документ изменили, то при
// попытке его сохранения программа попытается его перепровести
СтКонтрагент=Контрагент;
// Инициализируем переменную СтКонтрагент значением реквизита Контрагент
КонецПроцедуры
//-----------------------------------------------
Процедура Контрагент()
Если Контрагент<>СтКонтрагент Тогда
// В поле Контрагент содержимое изменилось
Договор="";
// Очищаем поле Договор
СтКонтрагент=Контрагент;
// Инициализируем переменную СтКонтрагент новым значением
// реквизита Контрагент
КонецЕсли;
КонецПроцедуры
Закроем форму;
Откроем Модуль документа;
Мы видим текст:
// ********************
Процедура ОбработкаПроведения()
//Здесь следует написать алгоритм проведения документа
КонецПроцедуры
Модуль документа служит для задания правил внесения изменений в механизмы хранения данных.
Перепишем процедуру ОбработкаПроведения:
Процедура ОбработкаПроведения()
// Предопределенная процедура, запускающая механизмы регистрации движений
Если Контрагент.Выбран()=0 Тогда
// Выбран() – метод, возвращающий состояние поля ввода = 1, если поле
// заполнено и 0 если нет
Предупреждение("Контрагент не выбран");
// Вызовем на экран информационное окно с сообщением
НеПроводитьДокумент();
// Указываем, что документ заполнен неправильно – он не должен быть проведен
КонецЕсли;
Если Договор.Выбран()=0 Тогда
Предупреждение("Договор не выбран");
НеПроводитьДокумент();
КонецЕсли;
Если Договор.ДатаДоговора>ДатаДок Тогда
// Договор еще не был заключен на дату документа
Предупреждение("Неверная дата договора");
НеПроводитьДокумент();
КонецЕсли;
// Теперь будем заполнять поля регистра "Взаиморасчеты"
Регистр.Взаиморасчеты.Контрагент = Контрагент;
Регистр.Взаиморасчеты.Договор = Договор;
Регистр.Взаиморасчеты.Сумма = Сумма;
// Движение – поступление денег за продаваемый нами товар
// ФлагДвижения = 4
Регистр.Взаиморасчеты.ФлагДвижения = 4;
// Наш долг возрос, либо долг контрагента уменьшился – на регистр
// пишем сумму приходом
Регистр.Взаиморасчеты.ДвижениеПриходВыполнить();
КонецПроцедуры
Закрываем модуль документа;
Закроем окно свойств документа;
Переходим к редактированию журнала. Находим журнал "ДвижениеДенег";
Входим в редактирование журнала;
Добавим новую графу;
Идентификатор – "Сумма";
В возможных значениях отметим Документ.ПриходДенег.Шапка.Сумма;
В выбранных значениях появилось указание на поле документа "Приход денег" "Сумма";
Входим в форму списка журнала;
Разместим графы журнала как будет удобнее, и поменяем им ширину, чтобы все было видно;
Закроем форму списка журнала и окно свойств журнала;
Сохраним конфигурацию;
2.14 Работа с документом.
Документ готов. Проверим его в работе.
Открываем 1С:Предприятие в монопольном режиме;
Через меню "Операции" команда "Управление оперативными итогами";
Ставим дату актуальности итогов на 01.10.2000;
Нажимаем [Установить];
Появился вопрос "Изменить Точку Актуальности итогов";
Отвечаем [Да];
Нам сообщают, что изменение точки актуальности завершено. Подтверждаем получение сообщения (подробнее см. "Руководство пользователя");
Выходим из окна управления итогами;
Из нового раздела меню "Документы" вызываем документ приход денег;
Номер документа – 1, Дата – 02.10.2000, Комментарий – "наш первый документ", Контрагент – "Винни-Пух и все все все", Договор – "№12 от 2 Октября 2000 г.", Сумма – 1000;
[Закрыть];
Нас спросят – сохранить ли документ? [Да];
Попросят указать время – в начало дня;
Входим в меню "Журналы". Выберем журнал "ДвижениеДенег";
Если мы в журнале ничего не видим, значит, у нас стоит не тот период просмотра журнала. Входим в меню Действия, команда "Интервал". Устанавливаем диапазон дат от 01.10.2000 до текущей даты;
Мы видим наш документ. Пиктограммка слева – голубенький листок бумажки. Это значит, что документ сохранен;
Откроем этот документ, дважды щелкнув его мышкой;
Теперь нажмем [ОК];
Нас спросят про сохранение документа – [Да];
Провести документ? – [Да];
Точка актуальности будет перенесена на новую дату. Продолжить? – [Да];
Нами точка Актуальности была выставлена на 01.10.2000, а документ от 02.10.2000 – точка актуальности перемещается на последний проведенный документ.
В журнале пиктограммка приобрела красную галочку – флаг проведения документа, и красную черточку внизу – признак того, что ТА (Точка Актуальности стоит на текущем документе);
Посмотрим, какие движения произвел наш документ;
Курсор на документ. Меню "Действия", команда "Движения документа". Появилось окошко. В нем галочка стоит на строке с надписью Взаиморасчеты – это означает, что движение было только по этому регистру;
Тут есть еще строчка – Реквизиты справочников. Документ при проведении может менять значения периодических реквизитов справочников! (Если, конечно, это прописать в процедуре ОбработкаПроведения).
Выбираем эту строку;
Появилось окно "Движения регистров Взаиморасчеты (Приход денег 1 (02.10.2000))";
Видим в списке движений одну строку со знаком плюс (+) – это был приход. Движение было только одно – как мы и написали;
Закроем 1С:Предприятие;
2.15 Отчет по долгам.
Мы теперь, по данным нашей программы, должны фирме "Винни-Пух и все все все" – 1000 ед. денег. Это мы можем определить из нашего единственного документа, но когда таких документов будет много, и контрагентов в документах будет тоже много, мы запутаемся. Пусть лучше машина сама показывает нам кто, кому, по какому договору и сколько должен. Для таких целей существуют отчеты. Простейший отчет – "список номенклатуры" – мы уже создавали. Этот отчет у нас был включен в форму списка справочника. Теперь мы создадим отчет, имеющий свою отдельную форму.
В дереве метаданных, в разделе отчеты, создаем новый отчет;
Идентификатор – "Взаиморасчеты";
А вот вставлять в интерфейс из визарда не будем. Мы потом сами ручками вставим;
Конструкторы никакие вызывать не будем – так напишем (либо скопируем с сей методички);
Появилась экранная форма отчета;
Добавим поле ввода. Идентификатор – ВыбДата, тип – дата;
В модуле формы пишем:
Процедура Сформировать()
Запрос=СоздатьОбъект("Запрос");
// Запрос – специальный объект в 1С, служит для получения структурированной
// выборки данных
ТЗ="
|Период с ВыбДата по ВыбДата;
|Контр = Регистр.Взаиморасчеты.Контрагент;
|Дог = Регистр.Взаиморасчеты.Договор;
|Сум = Регистр.Взаиморасчеты.Сумма;
|Функция СумКонОст = КонОст(Сум);
|Группировка Контр упорядочить по Контр.Код;
|";
// Это текст запроса. Подробности в "Описании языка" том 2
Если Запрос.Выполнить(ТЗ)=0 Тогда
Сообщить("Запрос не выполнен");
Возврат;
КонецЕсли;
// Если запрос будет не выполнен по какой либо причине, метод Выполнить()
// вернет 0. Мы сообщим пользователю о произошедшей ошибке, и
// командой Возврат – прервем выполнение процедуры
ИтогоМы=0;
ИтогоНам=0;
// В этих двух переменных мы будем хранить итоговую информацию по долгу
Таб=СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("");
Таб.ВывестиСекцию("Шапка");
Пока Запрос.Группировка("Контр")=1 Цикл
// Получаем очередную запись из запроса
ТЭ=Запрос.Контр;
// Во временную переменную передаем значение выборки
Долг=Запрос.СумКонОст;
// Определяем суммарный долг по текущему значению выборки
// Дальше уже все знакомые нам методы
Если ТЭ.ЭтоГруппа()=1 Тогда
НазГр=СокрЛП(ТЭ.Наименование);
Если Долг=0 Тогда
ИначеЕсли Долг>0 Тогда
Мы=Долг;
Нам=0;
ИначеЕсли Долг<0 Тогда
Мы=0;
Нам=-Долг;
КонецЕсли;
Таб.ВывестиСекцию("Группа");
Иначе
Наз="("+СокрЛП(Строка(ТЭ.Код))+") "+СокрЛП(ТЭ.Наименование);
Если Долг=0 Тогда
Продолжить;
ИначеЕсли Долг>0 Тогда
Мы=Долг;
Нам=0;
ИтогоМы=ИтогоМы+Мы;
ИначеЕсли Долг<0 Тогда
Мы=0;
Нам=-Долг;
ИтогоНам=ИтогоНам+Нам;
КонецЕсли;
Таб.ВывестиСекцию("Строка");
КонецЕсли;
КонецЦикла;
Таб.ВывестиСекцию("Итого");
Таб.ТолькоПросмотр(1);
Таб.ПараметрыСтраницы(1,100,1);
Таб.Показать("");
КонецПроцедуры
Перейдем на закладку таблица, создадим шаблон, такого вида:
Закроем форму отчета;
Теперь будем включать наш отчет в меню. В окне метаданных перейдем на закладку "Интерфейсы";
Меню Действия, команда "Редактировать". Редактировать меню;
Входим в редактирование строки "новая колонка...";
Название пишем "Отчеты";
[ОК];
Открываем появившийся раздел меню "Отчеты";
Открываем подраздел меню "новый...";
Выбираем объект – Отчеты.Взаиморасчеты;
Поля Название, Подсказка заполнились автоматически. Их можно поменять;
[ОК];
Меню Действия команда "Тест" вызовет окошко, где будет показано, как будет выглядеть наше меню;
Закрываем тестовое окно;
Закрываем окно редактирования меню;
Возвращаемся к дереву метаданных;
Сохраняем конфигурацию;
Входим в 1С:Предприятие;
Через меню Отчеты вызываем наш отчет "Взаиморасчеты";
Устанавливаем дату 02.10.2000;
Нажимаем [Сформировать];
Результат. Мы должны всем поставщикам 1000, из них Винни-Пуху 1000, а всего наш долг 1000. Что и требовалось;
2.16 Документ "Выплата денег".
Документ "Выплата денег" будет практически аналогичен документу "Приход денег". Поэтому мы его создадим простым копированием. И потом внесем в него ряд небольших изменений.
В дереве метаданных скопируем документ "ПриходДенег" в буфер обмена Windows;
Вставим из буфера обмена в раздел "Документы" копию;
Изменим Идентификатор на "ВыплатаДенег", аналогично изменим Синоним и комментарий;
Внесем соответствующие косметические изменения в форму документа;
В модуле проведения документа вместо строки:
Регистр.Взаиморасчеты.ДвижениеПриходВыполнить();
напишем
Регистр.Взаиморасчеты.ДвижениеРасходВыполнить();
В модуле проведения документа вместо строки:
Регистр.Взаиморасчеты.ФлагДвижения = 4;
напишем
Регистр.Взаиморасчеты.ФлагДвижения = 3;
В журнале "ДвижениеДенег" изменим реквизит "Сумма";
В выбранные значения добавим реквизит "Сумма" из нового документа;
Перейдем на закладку "Интерфейсы" и добавим в меню в раздел "Документы" наш документ "ВыплатаДенег";
Команду укажем – Документы.ВыплатаДенег.Ввести;
Закроем лишние окна;
Сохраним конфигурацию;
Откроем 1С:Предприятие;
Создадим новый документ типа "Выплата денег". Заполним его. Сохраним. Проведем. И полюбуемся на движения которые сформировал документ и результат, который выдаст нам отчет;
Глава 6
2.17 Документ "Изменение цен".
Мы уже упоминали, что документы при проведении могут изменять значения периодических реквизитов справочников. Разумеется, документы могут изменять значения и непериодических реквизитов, но это мало интересно. При изменении периодических, программа будет запоминать когда и с помощью чего меняли значения.
В справочнике "Номенклатура" мы имеем два реквизита интересующего нас типа: "ЦенаП" и "ЦенаР". В их свойствах мы указали, что они могут изменяться документами. Спроектируем такой документ.
Пусть наш документ будет иметь возможность изменять цену не одного товара, а любого количества. Значит наш документ будет содержать многострочную часть. Документ должен иметь возможность изменять сразу и цену поступления и цену реализации. При работе с ценами товара мы хотим видеть, какие цены были до изменения. Эти поля должны быть не редактируемые. Для документа будет заведен отдельный журнал. Создадим этот документ. Все данные по документу сведем в таблицу:
Идентификатор: ИзменениеЦен Журнал: ИзменениеЦен Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Оперативный учет: нет Может являться основанием для документа любого вида?: нет |
Дополнительно
Склад
Место хранения
С.Склады
Товар
Товар
С.Номенклатура
Сорт
Сорт
С.Сорт
Партия
Партия прихода товара
Д.Приходная
Накладная
Количество
Количество товара
Число 17.2
СуммаП
Сумма по цене поступления
Число 19.2
СуммаД
Сумма по цене документа
Число 19.2
ФлагДвижения
Характер движения
Число 1.0
+
Регистр "ОборотыТоваров" будет накапливать информацию по движению товара как между складами и контрагентами, так и между самими складами. Нас здесь не интересует – это приход или расход, нам важен сам факт движения. Но движение вообще – мало информативно для анализа. Необходимо движение за какой-либо период для сравнения как было раньше и как обстоят дела с оборотами сейчас. В качестве такого периода выберем, для примера, месяц.
Определимся теперь с измерениями. Нам нужно знать по какому складу какой товар какого сорта дал какой оборот. Таким образом мы имеем следующие измерения: "Склад", "Товар", "Сорт". Накапливать обороты мы будем по количеству в основной единице измерения товара и по сумме по цене учета (поступления). Реквизит будет такой же как и в регистре "ОстаткиТоваров". Сведем все в таблицу:
Идентификатор: ОборотыТоваров Тип: Обороты Периодичность: - месяц |
|||
Дополнительно
Склад
Место хранения
С.Склады
Товар
Товар
С.Номенклатура
Сорт
Сорт
С.Сорт
Количество
Количество товара
Число 17.2
СуммаУ
Сумма по цене учета
Число 19.2
ФлагДвижения
Характер движения
Число 1.0
+
Создадим в конфигураторе эти регистры. Только в регистре "ОстаткиТоваров" измерение "Партия" оставим пока неопределенного вида.
Глава 7
2.19 Приходная накладная.
Мы подошли к самой важной и сложной части задачи – описанию товарооборота. Первым документом у нас будет приходная накладная. Нам надо занести остатки на склады, иначе нечего будет перемещать, ни тем более списывать.
Возьмем обычную бумажную накладную. Номер накладной зависит от поставщика. Значит сделаем возможность заносить не уникальные номера приходных накладных. В ней кроме полей Номер документа и дата документа присутствуют стороны, участвующие в товарообороте - "От кого" и "Кому". В нашей приходной накладной им будут соответствовать поля "Поставщик" – наш контрагент и "Склад" – наш склад. Добавим еще одно поле – "Договор", нам надо знать, на основании чего произошла поставка товара.
Перейдем к табличной части. Имеется графа "Наименование товара". Этой графе будет соответствовать графа "Товар", Графы "Кол", "Цена", "Сумма" – так будет и у нас. Кроме этих граф добавятся следующие – "Ед" (единица измерения) – она покажет, в чем мы измеряем количество. "КолО" – если мы количество в графе "Кол", например, для яблок можем указать или в килограммах, или в ящиках, пишем в произвольной единице измерения, то в графе "КолО" – мы его приводим к основной единице измерения товара. На разные сорта товара будет разная цена, значит нам надо указывать сорт в новой графе "Сорт". Таким образом цена у нас будет – ценой выбранного сорта основной единицы измерения товара. По графам "КолО" и "Сумма" нам понадобится итог по колонке. Документ мы разместим в журнале накладных.
Идентификатор: ПриходнаяНакладная Журнал: Накладные Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: нет Автонумерация: нет Оперативный учет: да Может являться основанием для документа любого вида?: нет |
|||
Дополнительные функции
Вам предлагается самостоятельно реализовать следующие дополнительные функции:
Единицы измерения для каждого материала. У материала есть основная единица измерения (выбирается из справочника ЕдиницыИзмерения), в которых хранятся остатки в регистре. При приходовании и расходовании материала пользователь может указать любую единицу измерения, допустимую для данного материала (выбирается из подчиненного справочника ЕдИзмМатериалов). Программа пересчитывает указанное количество в основную единицу измерения с использованием коэффициента пересчета из справочника ЕдИзмМатериалов. В отчет добавляется новая колонка "Ед. изм."
Учет денежного выражения. В регистр Материалы добавляется новый ресурс СуммаРуб. (название Сумма не рекомендуется, так как есть встроенная функция Сумма в языке запросов). В отчете выводятся две колонки: Количество и Сумма. Должна быть возможность выводить только одну колонку по требованию пользователя. По колонке Сумма должны выводиться итоги по каждой группе материалов и по всему отчету.
Отчет о движении материалов за период.
Пользователь в диалоге указывает период. В отчете выводятся колонки: Материал, Остаток на начало период, Приход за период, Расход за период, Остаток на конец периода. Для ускорения работы отчета на больших базах можно создать оборотный регистр ДвижениеМатериалов, тогда каждый документ должен делать движения по двум регистрам.
Партионный учет. Списание материалов по средней себестоимости / по методу FIFO / LIFO. В регистр добавляется новое измерение Партия (типа Документ). При расходовании материала подсчитывается сумма списания по заданному методу. Метод задается пользователем в константе МетодСписанияМатериалов (выбирается из перечисления МетодыСписанияМатериалов).
Работенка