Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторная работа_1C__2_1.doc
Скачиваний:
19
Добавлен:
10.05.2015
Размер:
543.23 Кб
Скачать

2.22 Расходная накладная.

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

  1. В дереве метаданных в разделе Документы найдем подраздел Нумераторы;

  2. Создадим новый нумератор "Накладные";

  3. Периодичность – в пределах года, длина – 5, цифровой, контроль уникальности – да;

Расходная накладная будет располагаться в уже существующем журнале "Накладные". Данные по документу расходная накладная сведем в таблицу:

Идентификатор: РасходнаяНакладная Журнал: Накладные Нумератор: Накладные     Периодичность: Длина:        Тип: Уникальность:       Автонумерация: да Оперативный учет: да Может являться основанием для документа любого вида?:

Является основанием для

Вводится на основании

Шапка

Реквизит

Описание

ТипЗначения

Доп.

Покупатель

Кому ушел товар

С.Контрагенты

 

Договор

Основание отгрузки товара

С.Договора

 

Склад

Откуда отгрузили товар

С.Склады

 

Таблица

Реквизит

Описание

ТипЗначения

Доп.

Товар

Товар

С.Номенклатура

 

Сорт

Сорт товара

С.Сорт

 

Кол

Количество в произвольной ед. измерения

Число 8.2

+

Ед

Единица измерения

С.Единицы

 

КолО

Количество в основной ед. измерения

Число 8.2

+,И

Цена

Цена реализации

Число 7.2

+

Сумма

Сумма документа

Число 15.2

+,И

  1. Создадим новый документ;

  2. Заполняем свойства и реквизиты согласно таблицы;

  3. Создаем форму документа;

  4. Редактируем форму накладной по аналогии с приходной накладной;

  5. Поле реквизита "НомерДок" делаем недоступным для редактирования;

  6. Формулы в реквизиты диалога ставим такие же как и в приходной накладной. За исключением Поставщик(), ее заменяем на Покупатель(). И убираем процедуру из колонки "Цена", эту колонку делаем недоступной для редактирования;

  7. Процедуры в модуль документа заносим из модуля формы приходной накладной. Только везде ЦенаП меняем на ЦенаР, и меняем название процедуры Поставщик() на Покупатель(), и убираем процедуру Цена();

  8. Текстовые поля с итогами по колонкам таблицы можно просто скопировать из формы документа приходная накладная;

У нас цена реализации зависит от даты. Мы хотим, чтобы при изменении даты документа цены в строках документа соответственно менялись;

  1. Добавим функцию ДатаДок() в поле реквизита "ДатаДок";

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

  3. Войдем в окно редактирования свойств справочника Номенклатура;

  4. Нажимаем [Формы списка >];

  5. Выпал список. Выберем пункт "Редактировать";

  6. Появилось окно редактирования списка форм списка справочника;

  7. [Новый];

  8. Введем идентификатор "ДляПодбора". [ОК];

  9. Курсор на новой форме списка "ДляПодбора";

  10. Нажмем [Для выбора];

  11. Галочка во второй колонке переместилась, и встала напротив "ДляПодбора";

  12. [Открыть];

  13. В форме списка оставим только поля "Код" и "Наименование";

  14. Через меню Вставить командой "Текст" выберем элемент диалога текст для вставки;

  15. Укажем ему место для вставки в табличной части. Добавилась новая колонка. В ней мы будем выводить остаток товаров на рабочую дату;

  16. В свойствах этой колонки типа Текст пишем заголовок "Ост";

  17. В формулу пишем функцию Ост();

  18. Добавим в экранную форму поле ввода "Склад" типа С.Склады – остатки у нас будут по конкретному складу. Это поле сделаем недоступным;

  19. В модуль формы списка добавим функцию: Функция Ост()   ТекТовар=ТекущийЭлемент(); // Получаем текущий товар в строке КолТов=Регистр.ОстаткиТоваров.СводныйОстаток(Склад, ТекущийЭлемент(),,,"Количество"); // Получаем суммарный остаток по ресурсу "Количество" // по измерениям "Склад" и "Товар", по остальным измерениям суммируем Если КолТов<=0 Тогда     Возврат(""); // если товара на складе нет в поле Ост вернем пустую строку Иначе     Возврат(КолТов); // иначе вернем количество остатка КонецЕсли; КонецФункции

  20. Вернемся к форме документа расходная накладная;

  21. Добавим в экранную форму кнопку;

  22. Заголовок у нее будет "Подбор", формула – Подбор();

  23. В модуль формы добавим две процедуры: Процедура Подбор() // Эта процедура запускается по нажатию кнопки [Подбор]   ОткрытьПодбор("Номенклатура","ДляПодбора"); // Инициализируем механизм подбора и указываем, что подбирать мы // будем из справочника Номенклатура, используя форму списка "ДляПодбора"   УстановитьЗначениеВПодборе("Склад",Склад); // В форму подбора в поле "Склад" передаем значение склада из // текущего документа КонецПроцедуры //----------------------------------------------- Процедура ОбработкаПодбора(ВыбТов) // Предопределенная процедура, срабатывающая по событию – выбор // элемента ВыбТов из справочника   КолОст=Регистр.ОстаткиТоваров.СводныйОстаток(Склад,   ВыбТов,,,"Количество"); // Проверим остаток   Если КолОст<=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);     КонецЕсли;     АктивизироватьСтроку(); // установим курсор в документе на строку, которую мы ввели   КонецЕсли; КонецПроцедуры

  24. Перейдем теперь к написанию модуля проведения документа;

  25. Напишем в модуль документа следующее: Процедура ОбработкаПроведения()   РегОст=СоздатьОбъект("Регистр.ОстаткиТоваров");   Если СравнитьТА()=-1 Тогда // Проверяем, не проводится ли документ ранее точки актуальности итогов     РегОст.ВременныйРасчет(1);     РассчитатьРегистрыНа(ТекущийДокумент());   КонецЕсли; // Проверка на наличие на остатке   ВыбратьСтроки();   ФлагОтказа=0;   Пока (ПолучитьСтроку()>0) Цикл     Остат=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество");     Если Остат<КолО Тогда       Сообщить("Нет товара № " +СокрЛП(Товар.Код)+"/" +СокрЛП(Сорт.Наименование)+" в колич. " +КолО+" (имеется "+Остат+")");       ФлагОтказа=1;     КонецЕсли;   КонецЦикла; // аналогичную часть кода см. в отчете ОстаткиНаСкладе   Если ФлагОтказа=1 Тогда     НеПроводитьДокумент();     Возврат;   КонецЕсли; // Это см. документы Приход/Расход денег // По регистру взаиморасчетов   Регистр.Взаиморасчеты.Контрагент = Покупатель;   Регистр.Взаиморасчеты.Договор = Договор;   Регистр.Взаиморасчеты.Сумма = Итог("Сумма");   Регистр.Взаиморасчеты.ФлагДвижения = 2;   Регистр.Взаиморасчеты.ДвижениеРасходВыполнить();   Если Константа.МетодСписания=Перечисление.МетодСписания.ФИФО Тогда // Здесь будет записана методика списания по FIFO   ИначеЕсли Константа.МетодСписания=Перечисление.МетодСписания.ЛИФО                                                         Тогда // Здесь будет записана методика списания по LIFO   ИначеЕсли     Константа.МетодСписания=Перечисление.МетодСписания.По_среднему                                                         Тогда // Здесь будет записана методика списания по-среднему   КонецЕсли; КонецПроцедуры

  26. Начнем описание методик с FIFO;

  27. Заместо строки "// Здесь будет записана методика списания по 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.УдалитьСтроки(); // удаляем строки из временной таблицы. // Готовим ее под следующую строку документа КонецЦикла; Здесь мы воспользовались для определения партий механизмом прямой выгрузки данных из регистра в таблицу значений.

  28. Теперь опишем методику списания по LIFO. Мы, конечно можем, воспользоваться предыдущим примером, заменив строку       ТабЗн2.Сортировать("1+",1); На  ТабЗн2.Сортировать("1-",1);       // Сортировка документов по убывающей. Последний – сверху Но мы легких путей не ищем! Воспользуемся механизмом запроса.

  29. Заместо строки "// Здесь будет записана методика списания по LIFO" напишем: // Здесь будет записана методика списания по LIFO ВыбратьСтроки(); Пока ПолучитьСтроку()=1 Цикл   КолСпис=КолО;   Запрос="";   ТекстЗапроса="";   Если ИтогиАктуальны()=0 Тогда     ТекстЗапроса="     |Период с ДатаДок по ДатаДок;";   КонецЕсли;   ТекстЗапроса=ТекстЗапроса+"   |РегСклад=Регистр.ОстаткиТоваров.Склад;   |РегТовар=Регистр.ОстаткиТоваров.Товар;   |РегСорт=Регистр.ОстаткиТоваров.Сорт;   |РегПартия=Регистр.ОстаткиТоваров.Партия;   |РегКолич=Регистр.ОстаткиТоваров.Количество;   |РегСумма=Регистр.ОстаткиТоваров.СуммаП;   |Группировка РегПартия Упорядочить по РегПартия.ДатаДок;   |Функция КолКонОст=КонОст(РегКолич);   |Функция СумКонОст=КонОст(РегСумма);   |Условие (РегСклад=Склад);   |Условие (РегТовар=Товар);   |Условие (РегСорт=Сорт);";   Запрос=СоздатьОбъект("Запрос");   Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда     Сообщить("Документ не проведен");     НеПроводитьДокумент();     Возврат;   КонецЕсли;   Пока Запрос.Группировка("РегПартия",-1)=1 Цикл // В методе Группировка флаг –1 указывает, что сортировка по запросу // идет в порядке убывания. Более поздние документы идут первыми     Если КолСпис=0 Тогда       Прервать;     КонецЕсли;     ПартияСписания=Запрос.РегПартия;     Если  Запрос.КолКонОст>КолСпис Тогда       Списывать=КолСпис;       Стоимость=Окр((Запрос.СумКонОст/Запрос.КолКонОст)*Списывать,2,1);     ИначеЕсли Запрос.КолКонОст=КолСпис Тогда       Списывать=КолСпис;       Стоимость=Запрос.СумКонОст;     ИначеЕсли Запрос.КолКонОст<КолСпис Тогда       Списывать=Запрос.КолКонОст;       Стоимость=Запрос.СумКонОст;     КонецЕсли;     КолСпис=КолСпис-Списывать;     Регистр.ОстаткиТоваров.Склад = Склад;     Регистр.ОстаткиТоваров.Товар = Товар;     Регистр.ОстаткиТоваров.Сорт = Сорт;     Регистр.ОстаткиТоваров.Партия = ПартияСписания;     Регистр.ОстаткиТоваров.Количество = Списывать;     Регистр.ОстаткиТоваров.СуммаП = Стоимость;     Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*Списывать,2,1);     Регистр.ОстаткиТоваров.ФлагДвижения = 1;     Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);     Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();     Регистр.ОборотыТоваров.Склад = Склад;     Регистр.ОборотыТоваров.Товар = Товар;     Регистр.ОборотыТоваров.Сорт = Сорт;     Регистр.ОборотыТоваров.Количество = Списывать;     Регистр.ОборотыТоваров.СуммаУ = Стоимость;     Регистр.ОборотыТоваров.ФлагДвижения = 1;     Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);     Регистр.ОборотыТоваров.ДвижениеВыполнить();   КонецЦикла; КонецЦикла;

  30. Теперь опишем алгоритм списания по-среднему: // Здесь будет записана методика списания по-среднему ВыбратьСтроки(); Пока ПолучитьСтроку() = 1 Цикл   КолОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"Количество"); // Получаем суммарный остаток по указанным измерениям // по данному ресурсу   СумОст=РегОст.СводныйОстаток(Склад,Товар,Сорт,,"СуммаП");   ЦенОст=Окр(СумОст/КолОст,2,1);   Парт=ПолучитьПустоеЗначение("Документ.ПриходнаяНакладная"); // А это, что-бы заполнить хоть чем-нибудь измерение "Партия"   Регистр.ОстаткиТоваров.Склад = Склад;   Регистр.ОстаткиТоваров.Товар = Товар;   Регистр.ОстаткиТоваров.Сорт = Сорт;   Регистр.ОстаткиТоваров.Партия = Парт;   Регистр.ОстаткиТоваров.Количество = КолО;   Регистр.ОстаткиТоваров.СуммаП = Окр(ЦенОст*КолО,2,1);   Регистр.ОстаткиТоваров.СуммаД = Окр(Цена*КолО,2,1);   Регистр.ОстаткиТоваров.ФлагДвижения = 1;   Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);   Регистр.ОстаткиТоваров.ДвижениеРасходВыполнить();   Регистр.ОборотыТоваров.Склад = Склад;   Регистр.ОборотыТоваров.Товар = Товар;   Регистр.ОборотыТоваров.Сорт = Сорт;   Регистр.ОборотыТоваров.Количество = КолО;   Регистр.ОборотыТоваров.СуммаУ = Окр(ЦенОст*КолО,2,1);   Регистр.ОборотыТоваров.ФлагДвижения = 1;   Регистр.ОборотыТоваров.ПривязыватьСтроку(НомерСтроки);   Регистр.ОборотыТоваров.ДвижениеВыполнить(); КонецЦикла;

  31. Подредактируем журнал "Накладные";

  32. Изменим содержимое графы "Кол";

  33. Добавим в выбранные значения графы Документ.РасходнаяНакладная.КолО;

  34. Аналогично поступим и с графой "Сумма";