Документ "Приходная накладная" создан, в интерфейс внесен сам документ и его журнал. Давайте попробуем поработать с этим документом. Войдем в 1С:Предприятие и создадим Приходную накладную №1 от 02.01.2001.
Цены попытаемся вводить как с НДС, так и без НДС. Попробуем менять валюту. И наконец, проведем этот документ и посмотрим на получившуюся операцию и проводки. Создана одна операция на сумму 270 рублей и четыре проводки, три по дебету 10-ого счета на сумму 75, 100 и 50 рублей, и одна по дебету 19-ого счета на сумму 45 рублей. Документ попробуем проводить с разной валютой. Используем теперь документ "Учет НДС" для списания с налогов суммы уплаченного поставщику НДС за купленные нами комплектующие. Вводим УчетНДС №1 от 03.01.2001. Сумма – 45 рублей. Проводим. Смотрим на операцию и проводку. Посмотрим как действует журнал проводок (меню Действия, команда "Перейти в журнал проводок"). Попробуем разделить по журналам нашим флажком. Все работает.
Документ РасходныйОрдер.
Документ "Расходный ордер" на первый взгляд совершенно простой, всего одна проводка (Д 60 – К 50.1). Но мы должны этим документом погасить задолженность конкретному контрагенту по конкретной накладной (если она указана), а если что останется – другие накладные, начиная с более ранних. В ином случае мы будем погашать наиболее раннюю непогашенную приходную накладную. А если накладная указана, но она уже погашена, будем действовать по второму варианту. В документе нам надо знать кому погашать долг, по какому документу-основанию, на какую сумму. Этот документ мы будем держать в специальном журнале – "Кассовые", кроме него туда, со временем, попадет и "Приходный ордер".
Идентификатор: РасходныйОрдер Журнал: Кассовые Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет
Создавать операцию: Всегда Редактировать операцию: нет
Является основанием для
Вводится на основании
Шапка
Реквизит
Описание
ТипЗначения
Доп.
Получатель
кому
С.Контрагенты
Основание
за что платим
Д.ПриходнаяНакладная
Сумма
сколько
Число 12.2
3, +
Таблица
Реквизит
Описание
ТипЗначения
Доп.
В журнале "Кассовые" заведем графу таблицы – Сумма из реквизита документа "РасходныйОрдер" Сумма. Создадим форму журнала.
Создаем форму документа. Поля АвторДокумента, Курс, Основание делаем недоступными. В поля реквизитов Валюта и ДатаКурса вставляем формулу Валюта(), в поле Получатель формула Получатель(), добавляем две кнопки, первая [...] с формулой Основание(), вторая [Х] с формулой Основание="". В модуле формы пишем: Перем СтВалюта; Перем СтДатаКурса; Перем СтКурс; Перем СтПолучатель; //========================================================== Процедура ВводНового() АвторДокумента=СокрЛП(ИмяПользователя()); ФирмаДокумента=Константа.ОснФирма; Валюта=Константа.ОснВалюта; ДатаКурса=ДатаДок; Курс=1; Получатель=Константа.ОснПоставщик; СтВалюта=Валюта; СтДатаКурса=ДатаКурса; СтКурс=Курс; СтПолучатель=Получатель; КонецПроцедуры // Здесь ничего интересного //========================================================== Процедура ПриОткрытии() СтВалюта=Валюта; СтДатаКурса=ДатаКурса; СтКурс=Курс; СтПолучатель=Получатель; ПриЗаписиПерепроводить(1); КонецПроцедуры // И здесь ничего интересного //========================================================== Процедура Валюта() КурсС=СтКурс; КратС=СтВалюта.Кратность; КурсН=Валюта.Курс.Получить(ДатаКурса); КратН=Валюта.Кратность; Коэфф=Окр((КурсС*КратН)/(КурсН*КратС),6,1); // переводим в валюту документа Курс=КурсН; Сумма=Окр(Сумма*Коэфф,2,1); СтВалюта=Валюта; СтДатаКурса=ДатаКурса; СтКурс=Курс; КонецПроцедуры // Это уже было //========================================================== Процедура Получатель() Если СтПолучатель<>Получатель Тогда // Если мы изменили Получателя Основание=""; // поле с Основанием очищаем, документ-то к другому пока относится СтПолучатель=Получатель; КонецЕсли; КонецПроцедуры //========================================================== Процедура Основание() ТабЗн=СоздатьОбъект("ТаблицаЗначений"); // Создаем динамическую 2-х мерную таблицу ТабЗн.НоваяКолонка("Док","Документ.ПриходнаяНакладная",,,"ПрихНакл",18); ТабЗн.НоваяКолонка("Нум","Число",6,0,"Номер",6); ТабЗн.НоваяКолонка("Дат","Дата",10,0,"Дата",10); ТабЗн.НоваяКолонка("Сум","Число",14,2,"Сумма",14); // Определяем набор колонок ТабЗн.ВидимостьКолонки("1",0); // Колонка №1 невидима БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги"); // Создаем динамическую выборку по содержимому счетов БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш); // Указываем конкретный план счетов БухИтоги.ИспользоватьРазделительУчета(Константа.ОснФирма); // Указываем конкретную фирму БухИтоги.ИспользоватьСубконто(ВидыСубконто.Контрагент,Получатель,2); // Нам нужны итоги по конкретному контрагенту БухИтоги.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная,,1); // По всем его Приходным накладным БухИтоги.ВыполнитьЗапрос(,ДатаДок,"60"); // Сальдо нужно на конкретную дату по 60-му счету БухИтоги.ВыбратьСубконто(1); // Выбираем контрагентов Пока БухИтоги.ПолучитьСубконто(1)=1 Цикл // Получаем очередного контрагента, в нашем случае единственного БухИтоги.ВыбратьСубконто(2); // Выбираем документы (недооплаченные) // Субконто в перечне ИспользоватьСубконто() стоит вторым // значит ВыбратьСубконто(2) Пока БухИтоги.ПолучитьСубконто(2)=1 Цикл // Получаем очередной документ ТДок=БухИтоги.Субконто(2); // Нас интересует второе по упоминанию в перечне Субконто // указанных командой ИспользоватьСубконто() - документ КреС=БухИтоги.СКК(1); // Нам нужно сальдо кредитовое (счет пассивный) // на конец периода запроса по сумме (1) ТабЗн.НоваяСтрока(); // Создаем в динамической таблице пустую строку ТабЗн.Док=ТДок; ТабЗн.Нум=ТДок.НомерДок; ТабЗн.Дат=ТДок.ДатаДок; ТабЗн.Сум=КреС; // Заполняем ее КонецЦикла; КонецЦикла; ТабЗн.Сортировать("1+"); // Сортируем строки в динамической таблице по дате документа Стр=0; // Инициализируем переменную Рез=ТабЗн.ВыбратьСтроку(Стр,"Выберите приходную накладную"); // Предлагаем выбрать документ из списка Если Рез=1 Тогда // Если документ выбран Основание=ТабЗн.ПолучитьЗначение(Стр,"Док"); // Определяем, что выбрано и ставим его как Основание КонецЕсли; КонецПроцедуры // Все
Здесь, в последней процедуре мы воспользовались новым для нас объектом – Бухгалтерскими итогами. Это тот самый механизм, на котором по счетам хранятся результаты всех проводок по всем фирмам и всем счетам. Он аналогичен, во многом, регистрам Оперативного учета. Или они ему аналогичны... Займемся теперь процедурой проведения. Алгоритм действия, был описан нами в начале главы. Здесь мы впервые в этой конфигурации в процедуре проведения задействуем механизм партионного учета. Наша задача несколько упрощается тем, что в документе нет многострочной части. Попробуем реализовать алгоритм списания: Процедура ОбработкаПроведения() Если Получатель.Выбран()=0 Тогда Сообщить("Документ Расходный ордер №"+НомерДок+" от "+ДатаДок+" |не проведен. |Не выбран получатель"); НеПроводитьДокумент(); Возврат; КонецЕсли; КурсД=Курс; КратД=Валюта.Кратность; КурсУ=Константа.ОснВалюта.Курс.Получить(ДатаДок); КратУ=Константа.ОснВалюта.Кратность; Коэфф=Окр((КурсД*КратУ)/(КурсУ*КратД),6,1); // переводим в валюту документа СуммаОст=Окр(Сумма*Коэфф,2,1); БухИтоги=СоздатьОбъект("БухгалтерскиеИтоги"); БухИтоги.ИспользоватьПланСчетов(ПланыСчетов.Наш); БухИтоги.ИспользоватьРазделительУчета(ФирмаДокумента); Если Основание.Выбран()=1 Тогда // Указано за какую поставку платить БухИтоги.ИспользоватьСубконто(ВидыСубконто.Контрагент,Получатель,2); БухИтоги.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная, Основание,2); // Нас интересует конкретная накладная БухИтоги.ВыполнитьЗапрос(,ДатаДок,"60"); БухИтоги.ВыбратьСубконто(1); Пока БухИтоги.ПолучитьСубконто(1)=1 Цикл БухИтоги.ВыбратьСубконто(2); Пока БухИтоги.ПолучитьСубконто(2)=1 Цикл КреС=БухИтоги.СКК(1); // Смотрим, сколько недоплачено по этому документу Если КреС>0 Тогда // Недоплачено ПривязыватьСтроку(0); Операция.НоваяПроводка(); // Создаем проводку Операция.Дебет.Счет = СчетПоКоду("60",ПланыСчетов.Наш); Операция.Кредит.Счет = СчетПоКоду("50.1",ПланыСчетов.Наш); Операция.Дебет.Контрагент = Получатель; Операция.Дебет.ПриходнаяНакладная = Основание; Операция.Фирма = ФирмаДокумента; Операция.Комментарий = "Погашение долга перед поставщиком"; Операция.НомерЖурнала = "1"; Если СуммаОст>=КреС Тогда // Если оплачено больше чем недоплачено Операция.Сумма = КреС; Иначе // недоплачено больше чем оплачено этим документом Операция.Сумма = СуммаОст; КонецЕсли; СуммаОст=СуммаОст-КреС; // Сколько осталось нераспределенной оплаты КонецЕсли; КонецЦикла; КонецЦикла; КонецЕсли; Если СуммаОст>0 Тогда // Есть что распределять ТабЗн=СоздатьОбъект("ТаблицаЗначений"); ТабЗн.НоваяКолонка("Док","Документ.ПриходнаяНакладная"); ТабЗн.НоваяКолонка("Сум","Число",14,2); БухИтоги.ИспользоватьСубконто(ВидыСубконто.Контрагент,Получатель,2); БухИтоги.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная,,1); // Нас интересуют все накладные БухИтоги.ВыполнитьЗапрос(,ДатаДок,"60"); БухИтоги.ВыбратьСубконто(1); Пока БухИтоги.ПолучитьСубконто(1)=1 Цикл БухИтоги.ВыбратьСубконто(2); Пока БухИтоги.ПолучитьСубконто(2)=1 Цикл ТДок=БухИтоги.Субконто(2); Если ТДок<>Основание Тогда // Документ Основание мы уже оплатили один раз КреС=БухИтоги.СКК(1); ТабЗн.НоваяСтрока(); ТабЗн.Док=ТДок; ТабЗн.Сум=КреС; КонецЕсли; КонецЦикла; КонецЦикла; ТабЗн.Сортировать("1+"); ТабЗн.ВыбратьСтроки(); Пока ТабЗн.ПолучитьСтроку()=1 Цикл СумД=ТабЗн.Сум; ТДок=ТабЗн.Док; Если СуммаОст>СумД Тогда // Нераспределенная оплата пока больше недоплаченной суммы // текущего документа ПривязыватьСтроку(0); Операция.НоваяПроводка(); Операция.Дебет.Счет = СчетПоКоду("60",ПланыСчетов.Наш); Операция.Кредит.Счет = СчетПоКоду("50.1",ПланыСчетов.Наш); Операция.Дебет.Контрагент = Получатель; Операция.Дебет.ПриходнаяНакладная = ТДок; Операция.Фирма = ФирмаДокумента; Операция.Комментарий = "Погашение долга перед поставщиком"; Операция.НомерЖурнала = "1"; Операция.Сумма = СумД; СуммаОст=СуммаОст-СумД; // Уменьшаем остаток на сумму документа Иначе // Недоплаченная сумма текущего документа меньше нераспределенной оплаты ПривязыватьСтроку(0); Операция.НоваяПроводка(); Операция.Дебет.Счет = СчетПоКоду("60",ПланыСчетов.Наш); Операция.Кредит.Счет = СчетПоКоду("50.1",ПланыСчетов.Наш); Операция.Дебет.Контрагент = Получатель; Операция.Дебет.ПриходнаяНакладная = ТДок; Операция.Фирма = ФирмаДокумента; Операция.Комментарий = "Погашение долга перед поставщиком"; Операция.НомерЖурнала = "1"; Операция.Сумма = СуммаОст; Прервать; // Больше денег нет! КонецЕсли; КонецЦикла; КонецЕсли; Операция.Содержание = "Оплата комплектующих"; Операция.СуммаОперации = Окр(Сумма*Коэфф,2,1); Операция.Автор = АвторДокумента; Операция.Записать(); КонецПроцедуры
Теперь мы можем попробовать этот документ в деле, при разных начальных условиях, чтобы проверить работоспособность всех вариантов проведения.
2.36 Отчет "Счет60".
А теперь давайте состряпаем простенький отчетик по 60-ому счету. Нас будет интересовать начальное сальдо по этому счету, конечное сальдо за период, по контрагентам и по накладным. Можно воспользоваться конструктором, но создание отчета вручную несколько проще (меньше придется переделывать).
Создаем новый отчет "Счет60";
Добавляем поле ввода ВыбНачПериода типа Дата;
Добавляем поле ввода ВыбКонПериода типа Дата;
Добавляем кнопку [...] с Формулой: ВвестиПериод(ВыбНачПериода,ВыбКонПериода);
Добавляем текст с формулой: ПериодСтр(ВыбНачПериода,ВыбКонПериода);
В модуле формы пишем:
Процедура ПриОткрытии() // Установим начальные значения диапазона дат ВыбНачПериода = НачалоПериодаБИ(); ВыбКонПериода = КонецПериодаБИ(); КонецПроцедуры //========================================================== Процедура Сформировать() Таб = СоздатьОбъект("Таблица"); Таб.ИсходнаяТаблица("Таблица"); Ит = СоздатьОбъект("БухгалтерскиеИтоги"); Ит.ИспользоватьПланСчетов(ПланыСчетов.Наш); Ит.ИспользоватьРазделительУчета(Константа.ОснФирма); Ит.ИспользоватьСубконто(ВидыСубконто.Контрагент,,1); Ит.ИспользоватьСубконто(ВидыСубконто.ПриходнаяНакладная,,1); Ит.ВыполнитьЗапрос(ВыбНачПериода,ВыбКонПериода,"60",,, 1,"Операция","С"); Таб.ВывестиСекцию("Шапка"); ИтНачКред=0; ИтКонКред=0; ИтОбоКред=0; Ит.ВыбратьСубконто(1); Пока Ит.ПолучитьСубконто(1)=1 Цикл Контра=Ит.Субконто(1); НачКред=Ит.СНК(1); КонКред=Ит.СКК(1); ОбоКред=КонКред-НачКред; Таб.ВывестиСекцию("Контра"); ИтНачКред=ИтНачКред+НачКред; ИтКонКред=ИтКонКред+КонКред; ИтОбоКред=ИтОбоКред+ОбоКред; Ит.ВыбратьСубконто(2); Пока Ит.ПолучитьСубконто(2)=1 Цикл Дока=Ит.Субконто(2); НачКред=Ит.СНК(1); КонКред=Ит.СКК(1); ОбоКред=КонКред-НачКред; Таб.ВывестиСекцию("Дока"); КонецЦикла; КонецЦикла; // Здесь ничего нового Таб.ВывестиСекцию("Подвал"); Таб.ТолькоПросмотр(1); Таб.ПараметрыСтраницы(2); // Ориентация Ландшафт Таб.Показать("Сформировать",""); КонецПроцедуры
Соорудим шаблон таблицы
Попробуем в 1С:Предприятии наш новый отчет.
Документ НарядНаСборку.
Этим документом мы будем запускать в производство очередную партию комплектующих. В наряде будет указано с какого склада брать заготовки, кто из работников будет заниматься сборкой и, главное, какие изделия и в каком количестве должны быть сделаны. Количество и ассортимент комплектующих мы будем определять по справочнику Комплектация. Проводка документа (Д 20 – К 10.2). Документ должен будет списать со склада некоторое количество комплектующих, при этом списание должно идти по методу FIFO, в первую очередь из более ранних накладных. Документ будет помещен в специальный журнал.
Идентификатор: НарядНаСборку Журнал: НарядыНаСборку Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет
Создавать операцию: Всегда Редактировать операцию: нет
Является основанием для
Вводится на основании
Шапка
Реквизит
Описание
ТипЗначения
Доп.
Склад
С.Склады
Сборщик
С.Сотрудники
Таблица
Реквизит
Описание
ТипЗначения
Доп.
Изделие
С.Изделия
Кол
Число 5.0
+
В журнал добавим графу "Сборщик". Создаем форму документа. Поля Валюта, ДатаКурса, Курс удаляем. Поле АвторДокумента делаем недоступным. Добавляем кнопку [Заявка] с формулой Заявка(), по этой кнопке мы будем распечатывать перечень входящих в изделия комплектующих, с указанием общего количества. В табличную часть добавим поле текст с функцией Ост(Склад,Изделие), эта колонка будет показывать, для какого количества изделий хватит комплектующих (но, эта функция будет показывать только возможное количество, она, разумеется, не учитывает возможность участия комплектующего в разных изделиях). В поле табличной части Кол добавляем процедуру Кол(), эта процедура будет проверять, не превышает ли указанное количество изделий возможное, исходя из запасов на складе. Еще раз подобную проверку мы будем делать в модуле проведения.
В модуле формы документа пишем: Процедура ВводНового() АвторДокумента=СокрЛП(ИмяПользователя()); ФирмаДокумента=Константа.ОснФирма; Валюта=Константа.ОснВалюта; ДатаКурса=ДатаДок; Курс=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"; Операция.Сумма = СумО; Операция.Количество = Колич; СуммаОпер=СуммаОпер+СумО; ТабКом.УстановитьЗначение(СтрП,"Кол",КолП-Колич); ТабКом.УстановитьЗначение(СтрП,"Сум",СумП-СумО); // Опустошаем партию частично и переходим к следующей комплектующей Прервать; КонецЕсли; КонецЦикла; // По Партии КонецЦикла; // По Комплектующей КонецЦикла; // По Изделию Операция.Содержание = "Запуск производства"; Операция.СуммаОперации = СуммаОпер; Операция.Автор = АвторДокумента; Операция.Записать(); КонецПроцедуры Новый вариант хотя и сложнее, но работает правильно. И даже быстрее, так как обращений к Бухгалтерским итогам будет меньше или столько же, ведь они вынесены за цикл по изделиям. Проверим работу нашего документа с разными наборами данных.
Документ ПриходныйОрдер.
Товар отгружен, пора получить за него денежки. Деньги мы будем получать с покупателя наличными в кассу по Приходному ордеру. Проводка в документе будет всего одна (Д 50.1 – К 62). Списывать долг с конкретного покупателя мы будем в разрезе конкретной накладной на отгруз. Причем, если сумма в ордере больше непогашенного остатка по указанной накладной, то мы раскидаем остаток прихода денег по остальным непогашенным накладным клиента, а если накладная не указана, то спишем долг по самой ранней накладной. Этот документ будет очень похож на Расходный ордер, поэтому просто скопируем его и внесем небольшие изменения. Сведем данные по документу в таблицу:
Идентификатор: ПриходныйОрдер Журнал: Кассовые Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет
Создавать операцию: Всегда Редактировать операцию: нет
Является основанием для
Вводится на основании
Шапка
Реквизит
Описание
ТипЗначения
Доп.
Плательщик
от кого
С.Контрагенты
Основание
за что платит
Д.РасходнаяНакладная
Сумма
сколько
Число 12.2
3, +
Таблица
Реквизит
Описание
ТипЗначения
Доп.
В журнале "Кассовые" добавим в графу таблицы – Сумма из реквизита документа "ПриходныйОрдер" Сумма. Перейдем к редактированию формы документа. Сделаем все аналогично с Расходным ордером. Модуль формы напишите сами, он тоже аналогичен. Модуль проведения тоже аналогичен... Пишите сами для тренировки. Только учтите, что 62-ой счет пассивный и сальдо у него есть только по кредиту!
Документ Ведомость.
Ну вот, наконец, мы перешли к самому главному документу нашей конфигурации – Ведомости на зарплату. По сему наиважнейшему документу мы должны выплатить работникам трудовую копейку. Этот документ будет содержать список сотрудников и суммы к выплате, кроме того, в документе будет особая кнопка для занесения в ведомость всех сотрудников, по которым есть что платить. Сделаем в этом документе возможность редактировать операции. Сведем все в таблицу:
Идентификатор: Ведомость Журнал: Ведомости Нумератор: Нет Периодичность: Год Длина: 5 Тип: число Уникальность: да Автонумерация: да Может являться основанием для документа любого вида?: нет
Проводить: да Автоматическое удаление движений: да Автоматическая нумерация строк: да
Бухгалтерский учет: да Расчет: нет Оперативный учет: нет
Создавать операцию: Всегда Редактировать операцию: да