3. Создайте Форму документа. Диалога формы, которого может выглядеть следующим образом:
Поле Ввода Формула |
|
ДатаДок |
ДатаКурса=ДатаДок; Пересчет { ) |
ДатаКурса |
Пересчет () |
ПоСчету |
|
Сумма Ру б |
СуммаУЕ^? (Курс=0, 0, Сумма Ру б /Курс) |
Кнопка Формула |
|
Очистить Покупателя | Покупатель^ |
5. Поместите текст используемых процедур в Модуль формы:
Процедура ПриОткрытии
ПриЗаписиПерепроводить(1); КонецПроцедуры
Методические материалы обучения партнеров
апрель 2004 г.
72
1C предприятие 7.7. Компонента Оперативный учет
Процедура ^водНового ( Копирование ) Если КопиР°вание=0 Тогда
( )
КурС=1^онстанта.КурсУЕ. Получить (ДатаКурса) КонецЕсли; КонецПроцеЯуры
Процедура
// проверк^ правильности заполнения реквизитов Если покупатель Выбран ()=0 Тогда
предупреждение ( "Не выбран покупатель ! " } ;
КонецЕсл^1'
КонецПроцеЯуры - Г
// Процедур3 пересчета суммы в у.е.
// при изм^нении Даты' на которую получен курс
Процедура Пересчет ( )
Курс=Кон'станта КУРСУЕ Получить ( ДатаКурса ) ;
Если Кур^=0 Тогда Сумма/Е=0;
Иначе
КонецЕсл^'
ПосколькУ количество счетов, введенных в систему, может быть достаточно 5олыиим то д/™ облегчения работы с документом выбор счета будем производить только из спис^ка неоплаченных счетов. Чтобы подавить стандартный процесс выбора значения в Модуль формы добавим предопределенную процедуру
ПриНачалеВы^°Ра3начения )
Процедура Г^риНачалеВыбораЗначения(Знач1,Флаг) // при выбсЯР6 счета вызовем список неоплаченных счетов Если Зна«1="ПоСчетУ" Тогда
Флаг=0; //отменим стандартный процесс выбора значения
ПриВыб-°РеСчета ) КонецЕсл^1'
Текст сам*0"1 процедуры, которая выводит список неоплаченных счетов, может выглядеть сле^УюЩим образом:
73
Глава 4. Резервирование товаров
//вывод списка неоплаченных счетов. После выбора счета //остальные реквизиты заполняются автоматически Процедура ПриВыбореСчета{) Перем ВыбСтр;
Рег=СоздатьОбъект("Регистр.СостояниеЗаказа");
Ста=СравнитьТА(); *
Если Ста=-2 Тогда //документ еще не записан Если ДатаДокПолучитьДатуТА() Тогда Per.ВременныйРасчет(1); РассчитатьРегистрыПо(ДатаДок); КонецЕсли;
ИначеЕсли Ста=-1 Тогда
//дата и время существующего документа меньше даты и времени
// Точки актуальности итогов
Per.ВременныйРасчет{1);
РассчитатьРегистрыНа{ТекущийДокумент()); КонецЕсли;
ТЗ=СоздатьОбъект("ТаблицаЗначений"); // заполним таблицу значений данными из регистра Per.ВыгрузитьИтоги(ТЗ,,I); ТЗ.УдалитьКолонку("СуммаОтгрузки"); ТЗ.ВыбратьСтроки(); Пока ТЗ.ПолучитьСтроку()=1 Цикл Если ТЗ.СуммаОплаты=0 Тогда
ТЗ.УдалитьСтроку(); КонецЕсли; КОнецЦикла;
ТЗ.УстановитьПараметрыКолонки("Заказ",,,,"Счет",20); ТЗ.УстановитьПараметрыКолонки("СуммаОплаты","Число",
12,2,"Сумма долга",20); // выведем список неоплаченных счетов
Если ТЗ.ВыбратьСтроку(ВыбСтр,"Неоплаченные счета")=1 Тогда Если ВыбСтроО Тогда
ПоСчету=ТЗ.ПолучитьЗначение(ВыбСтрг"Заказ"); Покупатель=ПоСчету.Покупатель;
СуммаУЕ=ТЗ.ПолучитьЗначение(ВыбСтр,"СуммаОплаты"); Ч^умма Руб=СуммаУЕ* Кур с; КонецЕсли; КонецЕсли; КонецПроцедуры
Методические материалы обучения партнеров
апрель 2004 г.
74 1С:Предприятие 7.7. Компонента Оперативный учет
Необходимо отметить, что ранее для определения, проводится ли документ в реальном времени или «задним числом», мы использовали метод ИтоГиАктуальны(). Однако он относится к контексту Модуля документа и не может применяться в Модуле формы. Точно так же, как и метод вспомогательного объекта «Регистры» - Актуальность (). Поэтому в приведенной выше процедуре для тех же целей используется метод документа Сравнить та ). Кроме этого, особое внимание необходимо обратить на использование в тексте системных процедур РассчитатьРегистрыНа() и РассчитатьРегистрыПо{) .
Как следует из Блок-схемы информационных потоков, документ «ПриходДенег» записывает движения в регистры:
В процедуру ОбработкаПроведения () Модуля документа необходимо добавить строки:
//По регистру Взаиморасчеты
регистр.Взаиморасчеты.ДвижениеРасход(Покупатель,
СуммаУЕ,СуммаРуб); //По регистру СостояниеЗаказа Если ПоСчету.Выбран()=1 Тогда
Регистр.СостояниеЗаказа.ДвижениеРасход(ПоСчету,,
СуммаУЕ); КонецЕсли; //Оборотный регистр Регистр.ОборотыКлиента.ДвижениеПриход(Покупатель,СуммаУЕ);
Упражнение №4.4
Внесите необходимые изменения в Модуль документа «ПриходДенег».
Документ «СнятиеРезерва» предназначен для отмены резервирования това ров, если покупатель отказался их оплатить.
Упражнение №4.5
1. Воспользовавшись Конструктором, создайте документ «Снятие резерва»:
Глава 4. Резервирование товаров
2. Добавьте в документ реквизит шапки «ПоСчету», аналогичный одноименному реквизиту документа «ПриходДенег».
документа, диалог)
которой может выглядеть, так как это изображено на 4.3.
4.3. Форма документа
«Снятие Рез ерва»
4. При выборе счета предусмотрите
тпэттшзггписка" счетотггтго которым" осталсяг
не отгруженный и неоплаченный товар, -В |
этом случае текст Модуля формы может
быть следующим: --
Процедура ГТриОткрытим ()
ПриЗаписиПерепроводить(1); Конец11роцедурь1
//вывод списка счетов с неотгруженным и неоплаченным товаром Процедура ПриВыбореСчета()
Перем ВыбСтр;
Рег'СоздатьОбъект ( "Регистр. СостояниеЗаказа" ) ; Ста^СравнитьТА(};
"Если ста--2 Тогда //документ еще не записан Если ДатаДокПолучитьДатуТА() Тогда
--1- Per.
-РасечитатьРегистрыПо(ДатаДок);
"КонецЕсли;
//дачра и время существующего документа меньше //даты и времени Точки актуальности итогов ИначеЕсли Ста=-1 Тогда
Per.ВременныйРасчет(1) ;
(ТекущийДокумент () )7
"КонецЕсли;
~1Л1~создать Объект("СписокЗначений");
// выведем список счетов, имеющих резерв
Per.ВыОратьИтоги();
Пока Per. ПолучитьИтог 0=1" Цикл СТГТДо^а 1вйтЁГЭна че ни е ТТЗТ 3 а ка ^
.Заказ/Строка (ТЗ.Заказ)' + - ( отгрузка : 'Y 4-Формат (ТЗ."СуъШаОт'трузки,Ґ'410 . 2 ") оплата:"+Формат(ТЗ.СуммаОплаты,"410.2")+
~-уе '!_[ LJ
-ПНПёоп л а ч е иные с ч е та
{ВыбСтр,
Тог да
1ЦоСчету=ВыбСтр;
Методические материалы обучения партнеров
апрель 2004 г.
76
1С :Пред приятие 7.7. Компонента Оперативный учет
КонецЕсли; КонецПроцедуры
Процедура ПриНачалеВыбораЗначения{Знач1,Флаг) // при выборе счета вызовем список неоплаченных счетов Если Знач1="ПоСчету" Тогда
Флаг=0; //отменим стандартный процесс выбора значения ПриВыбореСчета() КонецЕсли;; КонецПроцедуры
потоков, документ
Снятие резерва с уменьшением сумм отгрузки и оплаты
5. Как следует из Блок-схемы информационных «СнятиеРезерва» записывает следующие движения:
Добавьте в процедуру Обра бот каПроведения (} Модуля документа следующий текст:
Процедура ОбработкаПроведения{) // по регистру РезервыТоваров Рег=СоздатьОбъект{"Регистр.РезервыТоваров");
-Рег1=СоздатьОбъект("Регистр.СостояниеЗаказа");
-Если ИтогиАктуальны{) =0 Тогда
Per.ВременныйРасчет{1};
Perl.ВременныйРасчет{1);
РассчитатьРегистрыНа(ТекущийДокумент()); КонецЕсли;
Рег.УстановитьФильтр(ПоСчету);
Пока Per.ПолучитьИтог(}=1 Цикл
Регистр.РезервыТоваров.ПоСчету=ПоСчету;
Регистр.РезервыТоваров.Товар^Рег.Товар;
Регистр.РезервыТоваров.РезервТовара=Рег.РезервТовара;
..__ Регистр.РезервыТоваров.ДвижениеРасходВыполнить(};
.-KG-; ю-^Ц-^кЛхх;- - -
// по регистру СостояниеЗаказа
СумОтгр=Рег1.Остаток(ПоСчету,"СуммаОтгрузки");
СумОпл=Рег1.Остаток(ПоСчету,"СуммаОплаты");
Если (СумОтгрХ)) или (СумОпл0) Тогда
Регистр.СостояниеЗаказа.ДвижениеРасход(Посчету,СумОтгр,
~ СумОпл) ; ,
Ко н е цЕ с л и ;
КонецПроцедуры
Методические материалы обучения партнеров
77
Глава 4. Резервирование товаров
4.3. Ввод документа «Расходная накладная» на основании документа «Счет»
Одним из режимов ввода новых документов в процессе работы пользователя с системой «1С:Предприятие» является режим ввода «на основании». В режиме «1С:Предприятия» ввод «на основании» позволяет добавлять новые документы, заполняя их реквизиты путем копирования информации из выбранного документа-образца. В отличие от простого копирования документов, в результате которого создается документ того же вида, что и документ-образец, режим ввода «на основании» позволяет создавать и переносить информацию в документ другого вида.
Для организации ввода документа в режиме «ввод на основании» необходимо проделать следующие действия:
Текст этой процедуры должен быть разработан специалистом, осуществляющим конфигурирование системы. Для облегчения задачи разработки процедуры ВводиаОсновании () в системе «1С:Предприятие» существует «Конструктор ввода на основании».
По условию задачи нам необходимо обеспечить возможность ввода Расходной накладной на основании Счета.
Упражнение'-№4,6
Идентификатор |
Основание |
Синоним |
Основание |
Комментарий |
Документ, на основании которого вводится накладная |
Тип значения |
Документ |
Вид |
Счет |
При ведении процесса купли-продажи на нашей фирме может возникнуть ситуация, когда зарезервированный по счету товар будет отгружаться частями, то есть апрель 2004 г.
73 1С:Предприятие 7.7. Компонента Оперативный учет
на основании одного документа «Счет» будет выписано несколько документов «Расходная накладная». Это тем более возможно, так как в счете не предусмотрен реквизит Склад^ а, следовательно, резервирование товара может происходить сразу на нескольких складах. Поэтому, после выбора для создаваемой накладной склада, первоначальное количество отгружаемого по накладной товара будет равно количеству товара, которое осталось отгрузить по данному счету. Если по счету осталось отгрузить товара больше, чем есть на складе, то в накладную будет внесен весь оставшийся на складе товар этого наименования.
Кроме того, запретим ввод «на основании» для накладной, если документ-основание не проведен или по нему полностью отгружен товар всех, присутствующих в счете, наименований.
Тогда процедура ВводНаОсновании () для документа «Расходная накладная» примет вид:
Процедура ВводНаОсновании(ДокОснование) Если ДокОснование.Проведен(}=0 Тогда
Предупреждение("Документ """+ДокОснование+
""" не проведен!. Ввод на основании запрещен."); СтатусВозврата(0); Возврат; КонецЕсли;
Рег^СоздатьОбъект("Регистр.РезервыТоваров"); Рег1=СоздатьОбъект("Регистр.ОстаткиТоваров"); Если Per.СводныйОстаток(ДокОснование,,"РезервТовара") =Ц
Тогда Предупреждение("По счету "+ДокОснование+
" все товары отгружены!"); СтатусВозврата(0); Возврат; КонецЕсли;
// заполним шапку документа Курс = ДокОснование.Курс; ДатаКурса = ДокОснование.ДатаКурса; Покупатель = ДокОснование.Покупатель; Основание = ДокОснование; ВвестиЗначение(Склад,"Выберите склад!"); РежимПровёдения=0; ДокОснование.ВыбратьСтроки(); Пока ДокОснование.ПолучитьСтроку()=1 Цикл
// найдем оставшееся количество зарезервированного товара Ост=Рег.Остаток(ДокОснование,
ДокОснование.Товар,"РезервТовара") Если Ост0 Тогда
Методические материалы обучения партнеров
79
Глава 4. Резервирование товаров
// заполним табличную часть документа
НоваяСтрока ( ) ; .
Товар=ДокОснование . Товар;
Единица = Товар. ЕдиницаИзмерения; :
Количество=0ст;
Цена=ДокОснование . Цена;
СуммаУЕ=Цена*Количество;
// проверим количество оставшегося товара на складе
Если Товар . Родитель . ВидНоменклатуры=
Перечисление . ВидНоменклатуры . Товар Тогда Ост=Рег1 .Остаток (Товар, Склад, "Количество") ; Если ОстКоличество Тогда Если Ост=0 Тогда
Сообщить ("Товар """+Товар-н
отсутствует!"
""" на складе """+Склад+ УдалитьСтроку ( ) ; Иначе
Количество=0ст; Сумма УЕ=Цена* Количество; КонецЕсли; КонецЕсли; КонецЕсли;
Сумма Руб=СуммаУЕ * Курс ; КонецЕсли; КонецЦикла;
Если КоличествоСтрок()=0 Тогда
СтатусВозврата(0) ; КонецЕсли; КонецПроцедуры
Упражнение №4.7
1. Предусмотрите аналогичное заполнение документа «Расходная накладная» в
случае изменения значения реквизита Основание. Для этого формула в свойствах
этого поля ввода введите имя процедуры ПриВыбореОснования (). Текст этой про-
цедуры может быть следующим:
// при вводе нового документа-основания // заполним реквизиты текущего документа Процедура ПриВыбореОснования()
УдалитьСтроки();
ВводНаОсновании(Основание); КонецПроцедуры
апрель 2004 г.
80 1C предприятие 7.7. Компонента Оперативный учет
2. В Модуле документа «Расходная накладная» добавьте необходимые строки
текста, связанные с движениями регистров «РезервыТоваров» и
«СостояниеЗаказа». После строки:
[Регистр. ОстаткиТоваров . ДвижениеРасходВыполнить () ; |
добавьте строки текста
//движение регистра РезервыТоваров Если Основание.Проведен()=1 Тогда
Регистр.РезервыТоваров.ДвижениеРасход(
Основание,Товар,Количество); КонецЕсли;
После строк:
Иначе
Сообщить ("На "+ДатаДок+", в строке №"+НомерСтроки4-
" совсем нет товара "+Товар+" !"); КонецЕсли;
строки текста, связанные с движением регистра «РезервыТоваров»
Иначе
//движение регистра РезервыТоваров Если Основание.Проведен()=1 Тогда
Регистр.РезервыТоваров.ДвижениеРасход(Основание,
Товар,Количество) КонецЕсли;
А после строки
Регистр.Взаиморасчеты.ДвижениеПриход{Покупатель,
Итог("СуммаУЕ"),Итог{"СуммаРуб"))
добавьте строки
//движение регистра СостояниеЗаказа Если Основание.Проведен{)=1 Тогда
Регистр.СостояниеЗаказа.ДвижениеРасход(Основание,
Итог("СуммаУЕ"),); КонецЕсли;
В заключение, необходимо упомянуть о следующем правиле, которое должно выполняться для документа-основания:
В Модуле документа, который может иметь подчиненные ему документы,
всегда должна присутствовать предопределенная процедура
ОбработкаУдаленияПроведения() после выполнения, которой все подчиненные данному документу документы станут не проведенными, либо в этой процедуре должна выполняться проверка на существование проведенных подчиненных документов и приниматься решение о возможности отмены проведения.
81
Глава 4. Резервирование товаров
Для случая, когда при отмене проведения документа-основания должна выполняться отмена проведения всех подчиненных ему документов, процедура для документа «Счет» может выглядеть следующим образом:
//отменим проведение всех документов, введенных на основании
//данного счета
Процедура ОбработкаУдаленияПроведения()
Докум^СоздатьОбъект("Документ");
Докум,ВыбратьПодчиненныеДокументы(
ДатаДок,,ТекущийДокумент());
Пока Докум.ПолучитьДокумент()=1 Цикл Докум.СделатьНеПроведенным{);
КонецЦикла; КонецПроцедуры
Заметим, что в этом случае, если пользователь случайно отменил проведение документа «Счет», который уже в последующих документах упомянут, то тогда будет отменена и вся «цепочка» документов. Это может приводить (при большом числе документов) к ненамеренным ошибкам в учете. Поэтому лучше все же в процедуре ОбработкаУдаленияПроведения () контролировать, что по данному документу уже была какая-то работа:
//отменим проведение всех документов, введенных на основании //данного счета
Процедура ОбработкаУдаленияПроведения() Докум=СоздатьОбъект("Документ"); Докум.ВыбратьПодчиненныеДокументы(ДатаДок,,
ТекущийДокумент{)); .
Пока Докум.ПолучитьДокумент()=1 Цикл Если Докум.Проведен()=1 Тогда
Сообщить("Для документа "+ТекущийДокумент()+ " нельзя отменить его проведение, т.к. он имеет "+ " подчиненные проведенные документы! "); .-СтатусВозврата(О) ; КонецЕсли; КонецЦикла; КонецПроцедуры
В этом случае пользователь вынужден будет осмысленными действиями вначале отменить проведение всех документов, которые подчинены данному документу, а уже затем отменить проведение и его самого.
Методические материалы обучения партнеров
апрель 2004 г.
82
Глава 5. Учет партий товаров
5.1. Принципы партионного учета
В учебной задаче предполагается, что учет товаров ведется в разрезе товаров и складов, причем списание проданных товаров осуществляется по методу FJFO или LIFO. Для выбора одного из этих методов в Конфигурацию добавим еще одну константу МетодСписания, типом значения которой будет одноименное перечисление, имеющее следующие значения: lifo, fifo, Средняя.
Метод FIFO основан на предположении, что себестоимость товаров, приобретенных в первую очередь, должна быть отнесена к товарам, проданным в первую очередь. Его называют - «метод оценки запасов по ценам первых покупок (first-in, first-out method - FIFO). Эффект от использования метода FIFO заключается в том, что материальные запасы на конец периода оцениваются по ценам последних покупок, а в себестоимости реализованной продукции используются цены первых покупок товара. В период постоянного роста цен метод FIFO дает наиболее высокий из возможных уровень чистого дохода. Причина в том, что фирма стремится повысить цены реализации при росте текущих цен, не принимая во внимание тот факт, что материальные запасы могли быть приобретены до момента роста цен. Соответственно в период снижения цен наблюдается обратный процесс. Поэтому основным недостатком метода FIFO является то, что он увеличивает влияние цикла экономического развития на показатель дохода.
Метод LIFO базируется на той предпосылке, что себестоимость товаров, приобретенных последними, используется для определения стоимости товаров, проданных в первую очередь, а себестоимость запасов на конец периода рассчитывается на основе себестоимости, приобретенных первыми. Его называют -«метод оценки запасов по ценам последних покупок (last-in, first-out method - LIFO). Безусловно, подобное допущение не сочетается с действительным движением товаров на многих предприятиях. Тем на менее сторонники метода LIFO считают, что наиболее точное определение прибыли возможно лишь при условии соотнесения текущей себестоимости товаров с текущей продажной ценой, не взирая на то, какие именно товары были фактически проданы. При движении цен как вверх, так и вниз метод LIFO предполагает, что себестоимость реализованной продукции отразит издержки в соответствии с уровнем цен на момент продажи. В результате метод LIFO показывает меньшую чистую прибыль в период проявления инфляционных процессов и, соответственно, большую чистую прибыль в период проявления де инфляционных процессов, чем любой другой метод. В качестве критического замечания по отношению метода LIFO можно отметить тот факт, что в Балансе материальные запасы оценены и отражены по ценам первых покупок, и эта оценка часто не совпадает с реальной стоимостью материальных запасов.
Методические материалы обучения партнеров
83
Глава 5. Учет партий товаров
Для обеспечения возможности партионного учета в регистр ОстаткиТоваров добавим новое измерение Партия со следующими свойствами:
Идентификатор |
Партия |
Синоним |
|
Комментарий |
|
Тип значения |
Документ |
Вид |
ПриходнаяНакладная |
Длина |
|
Точность |
|
Разделять Триады |
|
Отбор движений |
|
Отбор итогов |
Необходимо отметить, что следствием введения данного измерения в регистр ОстаткиТовара будет появление в Модуле документа «Приходная накладная»
следующей строки:
I Регистр.ОстаткиТоваров.Партия = ТекущийДокумент () ; [
Эта строка расположена перед строкой:
I Регистр. ОстаткиТоваров. ДвижениеПриходВыполнить () ; ]
Для определения текущего метода списания введем новую константу ОсновнойМетодСписания, возможные значения которой будут определяться вновь созданным перечислением МетодыСписания.
Кроме этого, в выражениях на встроенном языке в нашей конфигурации, где использовался метод регистра Остаток (Измерение 1,Измерение2, Ресурс) , его необходимо заменить методом СводныйОстаток (Измерение!,Измерение2, ,Ресурс). Аналогичным образом, в методе регистра ОстаткиТовара СводныйОстаток (Измерение!, , Ресурс) необходимо добавить символ «,»: СводныйОстаток (Измерение!, ,, Ресурс). Теперь осталось организовать списание товара по партиям при проведении документа «Расходная накладная». Реализуем эту возможность с помощью существующего в системе «1С:Предприятие» механизма запросов.
5.2. Запросы в системе «1С:Предприятие»
Для организации различных выборок мы можем использовать методы справочников, документов и регистров, которые для этого специально предназначены. Однако у каждого из типов объектов эти методы называются по-разному, поэтому часто использование только методов для организации выборок недостаточно для построения различных отчетов, обработок.
В системе «1С:Предприятие» имеется служебный объект - «Запрос», который, в частности, предназначен для построения отчетов по любым данным конфигурации.
апрель 2004 г.
84
1С:Предлриятие 7.7. Компонента Оперативный учет
Основная отличительная черта запросов - возможность создания массива данных с произвольными группировками, которые могут не совпадать с группировками, доступными при обработке справочников, документов, регистров и т.д. Более важной причиной использования механизма запросов при программировании модулей системы «1C: Пред приятие» является их более быстрая работа при обработке хранящихся в системе данных, чем работа встроенных методов регистров3.
Во всех программных модулях доступ к атрибутам и методам запросов может выполняться только через переменную, созданную функцией СоздатьОбъект. Порядок создания запроса:
Организация циклической обработки выборки.
Вот общая схема использования объекта:
НашЗалрос=СоздатьОбъект("Запрос");
//Создание объекта и присвоение ссылки на него переменной
НашЗапрос
ТекстЗапроса=
"//Далее следует текст запроса, написанный на языке
запросов";
//Если ошибка в запросе, то выход из процедуры
Если НашЗапрос.Выполнить(ТекстЗапроса)=0 тогда
Возврат;
КонецЕсли;
// Далее следует циклическая обработка данных по группировкам запроса.
Рассмотрим подробнее порядок написания текста запроса. В начале текста за-
проса указывается период, за который будет формироваться запрос:
{Период с Дата! по Дата2
//Дата! - начало периода формирования запроса
3 Конечно, можно так «плохо» написать запрос, что методы выборки для соответст-
вующего объекта метаданных могут «обогнать» запрос по скорости работы.
Методические материалы обучения партнеров
85
Глава 5. Учет партий товаров
|7/Дага2 - конец периода формирования запроса
Если период запроса не указан, то запрос формируется на точку актуальности итогов. Указание периода запроса актуально в том случае, когда запрос организует выборку по документам или регистрам. При организации выборки по справочникам период запроса значения имеет только в том случае, если у справочника есть периодические реквизиты.
После указания периода запросов следует объявление внутренних переменных:
Переменная, которая включает в выборку всех клиентов, встречающихся во
всех документах вида ПриходнаяНакладная за период запроса.
|Переменная1= Документ.ПриходнаяНакладная.Поставщик;
Переменная, которая включает в выборку все элементы справочника контрагентов.
|Переменная2=Справочник.Контрагенты.ТекущийЭлемент;
Переменная, которая включает в выборку все товары, встречающиеся в регист-
ре ОстаткиТоваров за период запроса.
I | ПеременнаяЗ = Регистр„ОстаткиТоваров.Товар; ]
Переменная, которая включает в выборку все остатки товаров за период запро
са^
[^Переменная4 = Регистр. ОстаткиТоваров . Количество; ^J
Переменная, которая включает в выборку все покупные цены товаров, которые
присутствуют на складе за период запроса.
11ПеременнаяЬ = Регистр.ОстаткиТоваров.Товар.ЦенаПокупки; |
После объявления внутренних переменных запроса, существует возможность постановки условий по включению в выборку данных:
Переменная! включила в выборку всех клиентов, встречающихся во всех документах вида ПриходнаяНакладная за период запроса. Среди операторов, которые используются для организации отбора записей по условию, выделяется
оператор «в». Этот оператор записывается следующим образом:
11Условие (Переменная! в ВыбПоставщик) ;
Где переменная ВыбПоставщик может быть:
1. Ссылкой на конкретный элемент справочника. В этом случае в выборку
попадут только те документы ПриходнаяНакладная, в которых рекви
зит Поставщик равен значению ВыбПоставщик. В данном случае эта за-
пись эквивалентна:
11Условие (Переменная! = ВыбПоставщик) ; |
2. Ссылкой на группу справочника. Тогда в выборку попадут те докумен
ты, в которых реквизит Поставщик принадлежит группе
ВыбПоставщик. В этом случае наша запись будет эквивалентна:
I Условие ((Переменная!.ПринадлежитГруппе(ВыбПоставщик))=1);
апрель 2004 г.
1C.'Предприятие 7.7. Компонента Оперативный учет
Пустым значением. Тогда в выборку попадут все документы вне зависимости от того, какое значение Поставщик в них указано. Эта ситуация соответствует тому как если бы мы вообще не указали условие в тексте запроса.
Ссылкой на объект типа «СписокЗначений». В этом случае в выборку попадут все документы, у которых Поставщик входит в список значений ВыбПоставщик. Такое условие мы могли бы записать следующим обра-
зом:
(ВыбПоставщик.Принадлежит (Переменная!) =1) ; |
ПеременнаяЗ включила в выборку все покупные цены товаров, которые при-(ргствуют на складе за период запроса.
Мы хотим поставить условие - включать в выборку только те результаты, ко-
ipiie имеют ненулевое значение:
Г/словие(Переменная50) ;
После задания условий формирования выборки, необходимо определить функ-которые будут использованы в запросе. Переменна я 4 включила в запрос все товаров за период запроса. Зададим функцию, которая будет суммировать
^результаты: _____
Г^ункция Функция! = Сумма (Переменная4) ; [
После определения необходимых в запросе функций, необходимо задать спо-06 и порядок группировки данных. Задавая несколько группировок, следует учи-чцвать, что при их циклической обработке сначала должно следовать обращение к ^уппировкам вышестоящих уровней. Например: необходимо создать отчет, пока-Э1в#ощий остатки всех товаров на всех складах за определенный период, путем ^работки регистра ОстаткиТоваров. Для этого следует создать выборку за период (Дата1 по Дата2. Выборка должна включать в себя:
Остатки по каждому наименованию товара на каждом склада
|ашЗапрос = СоздатьОбъект ( "Запрос") ;
1экстЗалроса="
[период с Дата! по Дата2;
Говар = Регистр. ОстаткиТоваров. Товар;
Склад = Регистр.ОстаткиТоваров.Склад;
(Сол = Регистр.ОстаткиТоваров.Количество;
Условие(Товар в ВыбТовар};
/порядок группировок
Группировка Товар;
Группировка Склад;
87
Глава 5. Учет партий товаров
{Функция Результат = КоыОст(Кол);"; //выполняем запрос
О Тогда
Если НашЗапрос.Выполнить(ТекстЗапроса) Возврат;
КонецЕсли;
В результате выполнения подобного запроса мы получим выборку, которая будет иметь следующую структуру:
Товар |
Склад |
Результат |
220 |
||
Товар! |
79 |
|
Tojjapl |
Склад! |
69 |
Товар! |
Склад2 |
10 |
Товар2 |
91 |
|
Товар2 |
Склад! |
80 |
Товар2 |
Склад2 |
21 |
ТоварЗ |
50 |
|
ТоварЗ |
Склад! |
50 |
В случае если порядок группировок в запросе поменять местами, изменится структура выборки:
//порядок группировок (Группировка Склад; (Группировка Товар;
Склад |
Товар |
Результат |
220 |
||
Склад! |
199 |
|
С '* -1 |
Товар! |
69 |
С ;1 |
Товар2 |
80 |
С ,1 |
ТоварЗ |
50 |
Склад2 |
10 |
|
Склад2 |
Товар 1 |
10 |
СкладЗ |
21 |
|
СкладЗ |
Товар2 |
21 |
После написания и выполнения запроса организуется циклическая обработка данных в порядке старшинства группировок:
Методические материалы обучения партнеров
апрель 2004 г.
1C предприятие 7.7. Компонента Оперативный учет
Глава 5. Учет партий товаров
89
НашЗапрос.Группировка(1}=1 Цикл //получение итоговых данных по текущему товару //по всем складам
Пока НашЗапрос.Группировка(2}=1 Цикл
//получение итоговых данных по товару
//по конкретному складу
КонецЦикла; КонецЦикла;
5.3. Текст Модуля документа «Расходная накладная»
Процедура СписатьПартии()
// присвоим переменной ссылку на текущий документ
ТД=ТекущийДокумент() ;
// присвоим переменной ссылку на объект типа "Запрос"
Запрос=СоздатьОбъект("Запрос"};
// формируем текст запроса
ТекстЗапроса="//{{ЗАПРОС(ПартииТоваров)";
// проверим, выполняется ли проведение документа в реальном
// времени
Если ИтогиАктуальны()=0 Тогда
// если нет, укажем период действия запроса
ТекстЗапроса=ТекстЗапроса+"
!Период с ТД по ТД;"; КонецЕсли;
ТекстЗапроса=ТекстЗапроса+"
// товары, встречающиеся в регистре за период запроса |Тов = Регистр.ОстаткиТоваров.Товар;
// склады, встречающиеся в регистре за период запроса |Скл = Регистр.ОстаткиТоваров.Склад;
// партии товаров, встречающиеся в регистре за период запроса {Партия = Регистр.ОстаткиТоваров.Партия; // остатки товаров
]Кол = Регистр.ОстаткиТоваров.Количество; // валютные остатки
|Вал = Регистр.ОстаткиТоваров. СтоимостьУЕ; // рублевые остатки
|Руб = Регистр.ОстаткиТоваров. СтоимостьРуб; // порядок группировок (Группировка Тов без групп; (Группировка Партия;
// добавим функции, позволяющие получить остатки на конец // периода
(Функция ОстКол = КонОст(Кол); (Функция ОстВал = КонОст(Вал); (Функция ОстРуб = КонОст(Руб);
которые хранятся на
// занесем в выборку только те товары, // складе, указанном в накладной |Условие(Скл=Склад) ; I"//}}ЗАПРОС
// проверим, выполнился ли запрос, если нет, то прекращаем
// выполнение процедуры
Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
СтатусВозврата(0) ;
Возврат; КонецЕсли;
/у/ характеризует порядок списания: если LIFO Напр*-!, FIFO /|/Напр=1 Если Константа. ОсновнойМетодСписания =
Перечисление.МетодыСписания.ЫГО Тогда
Напр=-1; Иначе
Напр=1; КонецЕсли;
// открываем выборку строк табличной части документа ВыбратьСтроки();
// цикл выбора строк спецификации документа :
Пока ПолучитьСтроку{)=1 Цикл // строка спозиционирована... // пропустим услуги Если Товар.Родитель.ВидНоменклатурыО
Перечисление.ВидНоменклатуры.Товар Тогда
// делаем запись по регистру "РезервыТоваров"
Если Основание.Проведен()=1 Тогда
Регистр.РезервыТоваров.ДвижениеРасход(Основание,Товар,
Количество); КонецЕсли;
// перейдем к следующей итерации цикла Продолжить; КонецЕсли;
// для каждого товара из накладной перейдем в начало выборки, // для гарантированого позиционирования по // старшей группировке "Тов" Запрос.вНачалоВыборки();
// перейдем на запись в выборке, содержащую данные для // конкретного значения группировки - Товар из строки // документа Если Запрос.Получить(Товар,)=1 Тогда
// если в выборке такой товар существует, то получим //остатки
ОстКол_во=Запрос.ОстКол; ОстСумВал=Запрос.ОстВал;
Методические материалы обучения партнеров
апрель 2004 г.
90
1C предприятие 7.7. Компонента Оперативный учет
ОстСумРуб=Запрос.ОстРуб; Иначе
ОстКол_во=0;
ОстСумВал=0;
ОстСумРуб=0; КонецЕсли;
// осуществим проверку наличия товара на складе Если ОстКол_воКоличество Тогда
// если товара нет или не хватает, выводим информацию в
// окно сообщений и переходим на следующую строку в
// документе
Сообщить(ИВ документе "+ТекущийДокумент()+
" в строке »"+НомерСтроки+" не хватило товара "+Товар+ " на складе "+Склад+"; реально есть "+ОстКол_во+"!н);
// подготовим отмену проведения документа
СтатусВозврата (0);
Продолжить; КонецЕсли;
// движение по регистру "ОстаткиТоваров"
// присвоим начальное значение переменной, в которой будет // храниться количество товара, оставшееся списать после // учета очередной партии ОсталосьСписать=Количество; // организуем цикл по партиям Пока (Запрос.Группировка{"Партия",Напр}=1) и
(ОсталосьСписатьХ)) Цикл
// если в партии меньше товара, чем осталось списать,
// то переменной присваиваем все имеющееся в партии
//количество, иначе списываем столько, сколько осталось
СписКол_во=Мин(Запрос.ОстКол,ОсталосьСписать);
// определим валютную и рублевую суммы
СписСумВал=?(Запрос.ОстКол=СписКол_во,Запрос.ОстВал, Окр(СписКол_во*Запрос.ОстВал/Запрос.ОстКол,2));
СписСумРуб=?(Запрос.ОстКол=СписКол_во,Запрос.ОстРуб, Окр(СписКол_во*Запрос.ОстРуб/Запрос.ОстКол,2));
// установим значения для измерений и ресурсов регистра
// по текущей партии
Регистр.ОстаткиТоваров.ПривязыватьСтроку(НомерСтроки);
Регистр.ОстаткиТоваров.Товар=Товар;
Регистр.ОстаткиТоваров.Склад=Склад;
Регистр.ОстаткиТоваров.Партия=3апрос.Партия;
Регистр.ОстаткиТоваров.Количество=СписКол_во;
Регистр.ОстаткиТоваров.СтоимВал=СписСумВал;
Регистр,ОстаткиТоваров.СтоимРуб=СписСумРуб;
Регистр.ОстаткиТоваров.ДвижениеРасходВыполнитьО ;
ОсталосьСписать=ОсталосьСписать-СписКол_во; КонецЦикла; // по партиям // делаем запись по регистру "РезервыТоваров"
Методические материалы обучения партнеров
Глава 5. Учет партий товаров
Если Основание.Проведен()=1 Тогда
Регистр.РезервыТоваров.ДвижениеРасход(Основание,Товар,
Количество); КонецЕсли; КонецЦикла; КонецПроцедуры
Процедура ОбработкаПроведения(ПараметрПроведения) // ПараметрПроведения=1 при частичном проведении //(только по остаткам) Если Последовательность.ДляРасходныхНакладных.Проверить(
ТекущийДокумент())=0 Тогда
// если последовательность нарушена, запретим проведение
// документа
Сообщить(
'Нарушена последовательность проведения документов!");
СтатусВозврата(0);
Возврат; КонецЕсли; // вызываем процедуру списания товаров по партиям
СписатьПартии();
// делаем частичное проведение, поэтому здесь процесс проведения прекращаем Если ПараметрПроведения=1 Тогда
РежимПроведения=1 ;
Возврат; Иначе
РежимПроведения=0 ; КонецЕсли;
//движение регистра Взаиморасчеты , '
Регистр.Взаиморасчеты.ДвижениеПриход(Покупатель, Итог("СуммаУЕ"),Итог("СуммаРуб"));
//движение регистра СостояниеЗаказа Если Основание.Проведен()=1 Тогда
Регистр.СостояниеЗаказа.ДвижениеРасход(Основание,
Итог("СуммаУЕ") , КонецЕсли; КонецПроцедуры
апрель 2004 г.
91
92
Глава 6. Отчеты
93
Глава 6. Отчеты
Поскольку увидеть содержимое регистров оперативного учета средствами самой системы «1С:Предприятие» невозможно, то для отображения накопленной в регистрах информации необходимо использовать отчеты. В системе «1С:Предприятие 7.7» имеется специальный конструктор отчетов, который позволяет быстро создать форму отчета.
Обычно, в начале новый отчет разрабатывают как внешний. А затем, когда отчет полностью отлажен, его вставляют в конфигурацию, используя для этого пункт контекстно-зависимого меню «Вставить внешний отчет.,,». Подробнее об этой и других возможностях можно прочитать в книге «1С:Предприятис Версия 7.7. Конфигурирование и администрирование часть 1».
Для построения отчетов по итогам, хранящимся в регистрах, необходимо на втором шаге в Конструкторе отчета выбрать Конструктор запросов.
6.1. Отчет «Взаиморасчеты»
Этот отчет должен отображать текущее состояние взаиморасчетов клиентом (клиентами) за период. При этом мы должны иметь возможность получить не только начальное значение остатка по регистру «Взаиморасчеты», приход и расход за период, но и развернутое сальдо на конец периода.
Заметим, что регистр остатков не имеет методов для извлечения оборотов (приход/расход) за некоторый период времени и, что получить такую информацию можно только с помощью объекта «Запрос».
6.1.1. Диалог формы отчета
В окне диалога данного отчета (см. 6.1) можно вводить даты начала и конца периода, за который желательно получить отчет, а также конкретного клиента. Выбор клиента для обработки взаиморасчетов с ним осуществляется из справочника «Контрагенты».
Отчет формирует результаты взаиморасчетов с покупателями. Кроме этого, он включает всю подробную информацию по взаиморасчетам с покупателями с точностью до первичных документов. В сформированном отчете есть возможность просмотреть любой документ, сделав двойной клик мышкой на графе содержащей
документ. 6.1. Диалог формы отчета
«Взаиморасчеты»
6.1.2. Алгоритм построения отчета
Форма отчета была построена с помощью конструктора запросов. После чего шаблон печатной формы был замен на шаблон, приведенный на 6.2.
о-лон г** ,.ной формы от11, гы»
Кроме этого в процедуру сформировать () были внесены некоторые измене-
ния.
Прежде чем привести текст модуля отчета полностью рассмотрим некоторые
его особенности, на которые нужно обратить внимание.
Следующий фрагмент:
Запрос = СоздатьОбъект("Запрос");
Если ВыбНачПериодаПолучитьДатуТА() Тогда
ВыбНачПериода=ПолучитьДатуТА(} ; КонецЕсли; Если ВыбКонПериода=ПолучитьДатуТА() Тогда
ВыбКонПериода=ПолучитьПустоеЗначение(); КонецЕсли; ТекстЗапроса = "//{{ЗАПРОС(Сформировать) [Период с ВыбНачПериода по ВыбКонПериода;
позволяет правильно сформировать период, за который будет осуществляться выборка движений из регистра «Взаиморасчеты». Первый оператор «Если» проверяет, что дата начала периода не позже ТА. И если это так, то устанавливает дату начала периода равной дате ТА. Второй оператор «Если» проверяет и устанавливает, если это нужно, дату конца периода не позднее ТА.
Для того чтобы получить развернутое сальдо можно воспользоваться добавочным ключевым словом «Когда» при описании функций запроса:
Методические материалы обучения партнеров
апрель 2004 г.
94
1С:Предприятие 7.7. Компонента Оперативный учет
Глава 6. Отчеты
(Функция ДолгКлиентаРуб = КонОст{СумРуб) когда(СумРуб=0) |Функция ДолгКлиентаВал = КонОст(СумВал) когда(СумВал=0) (Функция НашДолгРуб = КонОст{СумРуб) когда(СумРуб0); (Функция НашДолгВал = КонОст{СумРуб) когда{СумВал0};
Для того чтобы получить в отчете детализацию движений по документу нужно
воспользоваться предопределенной группировкой:
[ [Группировка Документ; _ |
Заметим, что функции НачОст{„.) и КонОст{...) не возвращают остатков на моменты до и после проведения документа соответственно при выборке по группировке «Документ».
При выводе секций отчета, когда группировка построена по справочнику,
обычно выделяют группы и элементы справочника разными секциями. В этом слу
чае целесообразно использовать метод ЭтоГруппа (...) объекта «Запрос», а не ана
логичный метод объекта «Справочник»:
Если Запрос.ЭтоГруппа(1)=1 Тогда Таб.ВывестиСекцию{"Группа");
Иначе
Таб.ВывестиСекцию("Клиент");
КонецЕсли;
Использование такой записи предпочтительнее по сравнению с Запрос. Клиент. ЭтоГруппа (), т.к. в этом случае в обработке будет участвовать 2 таблицы информационной базы вместо одной.
В результате выполнения запроса мы получим временную таблицу, которая будет иметь структуру, которую сокращенно можно представить следующим образом:
Клиент |
Документ |
Приход |
Расход |
9600 |
7200 |
||
Альтаир ТОО |
5280 |
2880 |
|
Алътаир ТОО |
Расходная накладная №1 |
2880 |
|
Альтаир ТОО |
Приход денег №1 |
2000 |
|
Альтаир ТОО |
Расходная накладная №3 |
2400 |
|
Альтаир ТОО |
Приход денег №2 |
880 |
|
Маренго |
4320 |
4320 |
|
Маренго |
Расходная накладная №2 |
4320 |
|
Маренго |
Приход денег №1 |
4000 |
|
Маренго |
Приход денег №2 |
320 |