суббота, 24 января 2015 г.

1с специалист задача 1.12

Условие задачи из сборника:

Компания занимается оптовой торговлей. Принята следующая схема работы: поступление товаров отражается документом «Приходная накладная». По предварительной договоренности с покупателем менеджер может оформить резерв (документ «Резервирование товара»), причем наличие товара в этот момент не важно, товар может отсутствовать. Непосредственно отгрузка товара покупателю отражается документом «Расходная накладная», при этом происходит снятие резерва. Учет товаров ведется в разрезе складов. В документах «Приходная накладная» и Расходная накладная» склад только один (склад – реквизит шапки). При проведении расходной накладной необходимо проверить наличие товара на складе и «свободного» (будет описано далее) товара. В том случае, когда товара недостаточно, документ не проводится и выводится соответствующее сообщение об ошибке. У каждого менеджера есть приоритет, чем больше приоритет, тем более ответственный менеджер и тем важнее его продажи. Таким образом, если два менеджера одновременно зарезервировали один и тот же товара, то менеджер с большим приоритетом может продать товар, зарезервированный менеджером с меньшим приоритетом. Менеджер с низким приоритетом продать чужой резерв не имеет права. Таким образом, «свободный» товар менеджера определяется как товар на всех складах минус резерв всех остальных менеджеров с приоритетом большим либо таким же, как и у текущего менеджера. Приоритет устанавливается для каждого менеджера индивидуально и может меняться не чаще чем 1 раз в месяц. При продаже необходимо использовать приоритет менеджера, актуальный на дату продажи. Себестоимость товара рассчитывается как средняя по складу. Необходимо создать отчеты по состоянию остатков и резервов на дату.
Решение задачи :
1. Создадим недостающие объекты конфигурации:
Справочник Склады,
Документ "Приходная накладная" добавляем реквизит "Склад".
Документ "Расходная накладная" добавляем реквизиты "Склад","Менеджер" (тип - справочник "физ лица")
Новый документ "Резервирование товара"
Реквизит шапки "Менеджер"
Табличная часть "Список Номенклатуры" с реквизитами "Номенклатура", "Количество".
Регистр "Остатки номенклатуры" добавим измерение "Склад"
Новый регистр "ТоварыВРезерве" измерения "Номенклатура", "Менеджер", ресурс -Количество.
Регистр сведений "CтатусыМенеджеров" с периодичностью месяц, измерение "Менеджер", ресурс "Приоритет".

2) Документ "Приходная накладная".
Создаем форму документа, в ней реализуем пересчет для реквизитов ТЧ "Цена", "Количество"
&НаКлиенте
Процедура СписокНоменклатурыКоличествоПриИзменении(Элемент)
ОМ.РассчитатьСумму(Элементы.СписокНоменклатуры.ТекущиеДанные);
КонецПроцедуры

&НаКлиенте
Процедура СписокНоменклатурыЦенаПриИзменении(Элемент)
ОМ.РассчитатьСумму(Элементы.СписокНоменклатуры.ТекущиеДанные);
КонецПроцедуры

вызывается процедура общего модуля ОМ( с признаком "клиент").

Процедура РассчитатьСумму(ТекСтрока) Экспорт
ТекСтрока.Сумма = ТекСтрока.Количество * ТекСтрока.Цена;
КонецПроцедуры

Документ является регистратором регистра "Остатки номенклатуры", С помощью конструктора заполним обработку проведения.

Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиНоменклатуры.Записывать = Истина;
Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;
Движение.Сумма = ТекСтрокаСписокНоменклатуры.Сумма;
КонецЦикла;
КонецПроцедуры

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаПоДокументу = СписокНоменклатуры.Итог("Сумма");
КонецПроцедуры

3. Переходим к документу "Резервирование товара". Он является регистратором для регистра "ТоварыВРеерве".Аналогично с помощью конструктора движений забацаем проведение.
Процедура ОбработкаПроведения(Отказ, Режим)
 Движения.ТоварыВРезерве.Записывать = Истина;
 Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл
Движение = Движения.ТоварыВРезерве.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Движение.Менеджер = Менеджер;
Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;
КонецЦикла;
КонецПроцедуры

4. Переходим к документу "Расходная накладная товара". Аналогично приходной накладной создаем форму и реализуем пересчет ТЧ.
На этом прелюдия закончена, переходим к обработке проведения.
Комментировать код не буду просто выложу его.

Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаПоДокументу = СписокНоменклатуры.Итог("Сумма");
КонецПроцедуры

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
//1. Очищаем наборы записей
Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.ОстаткиНоменклатуры.Очистить();
Движения.ОстаткиНоменклатуры.Записать();
Движения.ТоварыВРезерве.Записывать = Истина;
Движения.ТоварыВРезерве.Очистить();
Движения.ТоварыВРезерве.Записать();
//2 Установим блокировки
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать();
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыВРезерве");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать();
// Сам запрос
Запрос = Новый("Запрос");
Запрос.Текст ="ВЫБРАТЬ
             | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
             | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество
             |ПОМЕСТИТЬ ДокТЧ
             |ИЗ
             | Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
             |ГДЕ
             | РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка
             |
             |СГРУППИРОВАТЬ ПО
             | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура
             |
             |ИНДЕКСИРОВАТЬ ПО
             | Номенклатура
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             | ОстаткиНоменклатурыОстатки.Номенклатура,
             | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК НаСкладеКол,
             | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК НаСкладеСум
             |ПОМЕСТИТЬ ОстаткиНаСкладе
             |ИЗ
             | ДокТЧ КАК ДокТЧ
             | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
             | &ТочкаИтогов,
             | Номенклатура В
             | (ВЫБРАТЬ
             | ДокТЧ.Номенклатура
             | ИЗ
             | ДокТЧ)
             | И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки
             | ПО ДокТЧ.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             | ОстаткиНоменклатурыОстатки.Номенклатура,
             | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
             | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ОстатокСум
             |ПОМЕСТИТЬ ОстаткиНаВсехСкладах
             |ИЗ
             | ДокТЧ КАК ДокТЧ
             | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
             | &ТочкаИтогов,
             | Номенклатура В
             | (ВЫБРАТЬ
             | ДокТЧ.Номенклатура
             | ИЗ
             | ДокТЧ)) КАК ОстаткиНоменклатурыОстатки
             | ПО ДокТЧ.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             | ТоварыВРезервеОстатки.Номенклатура,
             | ТоварыВРезервеОстатки.Менеджер,
             | ЕСТЬNULL(ТоварыВРезервеОстатки.КоличествоОстаток, 0) КАК Резерв,
             | CтатусыМенеджеровСрезПоследних.Приоритет
             |ПОМЕСТИТЬ ВсеРезервы
             |ИЗ
             | ДокТЧ КАК ДокТЧ
             | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыВРезерве.Остатки(
             | &ТочкаИтогов,
             | Номенклатура В
             | (ВЫБРАТЬ
             | ДокТЧ.Номенклатура
             | ИЗ
             | ДокТЧ)) КАК ТоварыВРезервеОстатки
             | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.CтатусыМенеджеров.СрезПоследних(, ) КАК CтатусыМенеджеровСрезПоследних
             | ПО ТоварыВРезервеОстатки.Менеджер = CтатусыМенеджеровСрезПоследних.Менеджер
             | ПО ДокТЧ.Номенклатура = ТоварыВРезервеОстатки.Номенклатура
             |ГДЕ
             | CтатусыМенеджеровСрезПоследних.Менеджер <> &ТекМенеджер
             | И CтатусыМенеджеровСрезПоследних.Приоритет >= &ТекПриоритет
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             | ОстаткиНаВсехСкладах.Номенклатура КАК Товар,
             | ОстаткиНаВсехСкладах.ОстатокКол,
             | ОстаткиНаВсехСкладах.ОстатокСум,
             | ВЫБОР
             | КОГДА ЕСТЬNULL(ОстаткиНаВсехСкладах.ОстатокКол, 0) - ЕСТЬNULL(ВсеРезервы.Резерв, 0) > 0
             | ТОГДА ЕСТЬNULL(ОстаткиНаВсехСкладах.ОстатокКол, 0) - ЕСТЬNULL(ВсеРезервы.Резерв, 0)
             | ИНАЧЕ 0
             | КОНЕЦ КАК СвободныйОстаток
             |ПОМЕСТИТЬ ДоступныеОстатки
             |ИЗ
             | ДокТЧ КАК ДокТЧ
             | ЛЕВОЕ СОЕДИНЕНИЕ ОстаткиНаВсехСкладах КАК ОстаткиНаВсехСкладах
             | ПО ДокТЧ.Номенклатура = ОстаткиНаВсехСкладах.Номенклатура
             | ЛЕВОЕ СОЕДИНЕНИЕ ВсеРезервы КАК ВсеРезервы
             | ПО ДокТЧ.Номенклатура = ВсеРезервы.Номенклатура
             |;
             |
             |////////////////////////////////////////////////////////////////////////////////
             |ВЫБРАТЬ
             | ДокТЧ.Номенклатура,
             | МАКСИМУМ(ДокТЧ.Количество) КАК Количество,
             | МАКСИМУМ(ОстаткиНаСкладе.НаСкладеКол) КАК НаСкладеКол,
             | МАКСИМУМ(ОстаткиНаСкладе.НаСкладеСум) КАК НаСкладеСум,
             | МАКСИМУМ(ЕСТЬNULL(ДоступныеОстатки.СвободныйОстаток, 0)) КАК СвободныйОстаток,
             | МАКСИМУМ(ЕСТЬNULL(ТоварыВРезервеОстатки.КоличествоОстаток, 0)) КАК РезервМенеджера
             |ИЗ
             | ДокТЧ КАК ДокТЧ
             | ЛЕВОЕ СОЕДИНЕНИЕ ОстаткиНаСкладе КАК ОстаткиНаСкладе
             | ПО ДокТЧ.Номенклатура = ОстаткиНаСкладе.Номенклатура
             | ЛЕВОЕ СОЕДИНЕНИЕ ДоступныеОстатки КАК ДоступныеОстатки
             | ПО ДокТЧ.Номенклатура = ДоступныеОстатки.Товар
             | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыВРезерве.Остатки(
             | &ТочкаИтогов,
             | Менеджер = &ТекМенеджер
             | И Номенклатура В
             | (ВЫБРАТЬ
             | ДокТЧ.Номенклатура
             | ИЗ
             | ДокТЧ)) КАК ТоварыВРезервеОстатки
             | ПО ДокТЧ.Номенклатура = ТоварыВРезервеОстатки.Номенклатура
             |
             |СГРУППИРОВАТЬ ПО
             | ДокТЧ.Номенклатура";
 
 
 
 ТочкаИтогов = Новый Граница(МоментВремени(),ВидГраницы.Исключая);
 Отбор = Новый("Структура");
 Отбор.Вставить("Менеджер", Менеджер);
 Приоритет = РегистрыСведений.CтатусыМенеджеров.ПолучитьПоследнее(Дата,Отбор).Приоритет;
 
 Запрос.Параметры.Вставить("ТекМенеджер",Менеджер);
 Запрос.Параметры.Вставить("ТочкаИтогов", ТочкаИтогов);
 Запрос.Параметры.Вставить("ТекПриоритет",Приоритет);
 Запрос.Параметры.Вставить("Ссылка", Ссылка);
         Запрос.Параметры.Вставить("Склад", Склад);

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


5) Переходим к отчетам.
Отчеты "Остатки товаров" идентичен отчету из предыдущей задачи (1.11), а отчет "Резервы товаров" аналогичен отчету "Остатки товаров" только вместо склада здесь менеджер.








Комментариев нет:

Отправить комментарий