понедельник, 19 января 2015 г.

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

Условие задачи из сборника:
Компания занимается оптовой торговлей. Поступление товаров отражается
документом «Приходная накладная», продажа - «Расходная накладная». Продажа
происходит с учетом единиц измерения, т.е. для каждой номенклатурной позиции
может быть произвольное количество единиц измерения, например: штука; пачка
из 10 штук; контейнер из 500 штук и т.д. Если в накладной будет указана продажа
3-х пачек, то должны быть списаны 30 штук. Кроме того, в расходной накладной
могут также быть указаны услуги (например, доставка). И товары и услуги
необходимо указывать в одной табличной части.
Учет товаров ведется в разрезе складов. В документах по поступлению и
продаже товаров указан только один склад (склад – реквизит шапки).
При продаже себестоимость товара рассчитывается как средняя по всей
компании в целом, и проверяется остаток на складе, с которого производится
отгрузка. Например, если купили 1 рулон утеплителя за 1000 рублей и
оприходовали его на первый склад, а второй такой же рулон утеплителя купили за
2000 рублей, но оприходовали на второй склад, то при продаже себестоимость
этого утеплителя будет рассчитана как средняя, т.е. составит (1000+2000)/2 = 1500
рублей, и продать возможно не более одного рулона с каждого склада.
Создать отчет (с использованием плана видов характеристик) о движении
материалов с заданной характеристикой «Производитель». Отчет должен
формироваться за указанный период для выбранного склада по количеству и
сумме.



Решение.
Из условия задачи ясно что необходимо добавить в регистр  "ОстаткиНоменклатуры" измерение "ЕдиницаИзмерения", с типом соответсвующего справочника.
Так как такого справочника не существует в каркасной конфигурации, то создаем и его.
Аналогично с измерением "склад", так как учет ведется в разрезе складов.
В имеющемся регистре "Остатки номенклатуры" будем вести учет количества по складам, а себестоимость будем учитывать в новом регистре "Себестоимость" с измерениями "Номенклатура" и "Единица измерения" и ресурсами "Количество" и "Сумма".
Конечно велик соблазн "решить вопрос" одним регистром, но это приведет к грубой ошибке.
Допустим получили на Склад1 товар1 в количестве 1шт по 1 000 руб, а на склад2 товар1 1 шт. по 2000 руб, При списании со склада 1 по условию задачи "уйдет" 1шт на сумму 1500 руб. И останется о шт на сумму -500руб.



Переходим в документу "Приходная накладная".
Добавляем реквизиты "Склад" в шапку и "Единица измерения" в ТЧ.
Добавляем форму документа.
С помощью конструктора движений заполняем обработку проведения.


Процедура ОбработкаПроведения(Отказ, Режим)

Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.Себестоимость.Записывать       = Истина;

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

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


КонецПроцедуры


Добавляем процедуру

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

КонецПроцедуры


В форме документа реализуем пересчет суммы ТЧ.
Для этого добавим  2 процедуры (для количества и цены), которые вызовут процедуру общего модуля.
&НаКлиенте
Процедура СписокНоменклатурыКоличествоПриИзменении(Элемент)
Пересчет();
КонецПроцедуры

&НаКлиенте
Процедура СписокНоменклатурыЦенаПриИзменении(Элемент)
Пересчет();
КонецПроцедуры

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

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

Общий модуль должен быть с признаком "Клиент".

Переходим в документу "Расходная накладная".
В справочник "Номенклатура" добавляем реквизит  ВидТовара "ПеречислениеСсылка.ВидыНоменклатуры"
Аналогично документу "Приходная накладная" добавляем реквизиты Склад и ЕИ (Обязательные для заполнения), в модуле формы добавляем те же процедуры пересчета.
Теперь самое основное: пишем обработку проведения.(текст ниже).

1) Сначала поместим ТЧ документа во временную таблицу, так как эта таблица будет использоваться в последующих 2-х запросах.
2) Согласно новой методике проведения сначала безусловно списываем все количество из ТЧ. (кроме услуг конечно).
3) Запишем движения
4) Проверяем не ушли ли в минус при этом, если да то все - отбой, ахтунг, возврат)
5) Устанавливаем блокировку  на номенклатуру ТЧ для того чтобы одновременно товары их не использовали несколько транзакций.
6) Устанавливаем блокировку. Полезно  для того чтобы не "уйти в минус" и избежать взаимных блокировок.
7) Движение по регистру "Себестоимость".


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

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.ОстаткиНоменклатуры.Очистить();


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

Запрос.Параметры.Вставить("Ссылка", Ссылка);
Запрос.Параметры.Вставить("ВидТовара", Перечисления.ВидыНоменклатуры.Услуга);
Результат = Запрос.Выполнить();

// 2. Выполним проведение документа
Для каждого Стр Из СписокНоменклатуры Цикл
Если Стр.Номенклатура.ВидТовара = Перечисления.ВидыНоменклатуры.Услуга Тогда
Продолжить;
КонецЕсли;

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

// 3. Записываем движения
Движения.Записать();


//4  Проверяем остатки, не ушли ли в минус

Запрос.Текст ="ВЫБРАТЬ
| ДокТЧ.Номенклатура,
| ДокТЧ.ЕдиницаИзмерения,
| ДокТЧ.Количество,
| ДокТЧ.Склад,
| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
| ОстаткиНоменклатурыОстатки.Номенклатура.Представление
|ИЗ
| ДокТЧ КАК ДокТЧ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
| &ТочкаИтогов,
| Номенклатура В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| ДокТЧ.Номенклатура
| ИЗ
| ДокТЧ)
| И Склад = &Склад) КАК ОстаткиНоменклатурыОстатки
| ПО ДокТЧ.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
| И ДокТЧ.ЕдиницаИзмерения = ОстаткиНоменклатурыОстатки.ЕдиницаИзмерения
| И ДокТЧ.Склад = ОстаткиНоменклатурыОстатки.Склад
|ГДЕ
| ОстаткиНоменклатурыОстатки.КоличествоОстаток < 0";

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

КонецЕсли;


Если Отказ Тогда
Возврат;
КонецЕсли;



//5
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры ;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать();

//6
Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
Движения.Себестоимость.БлокироватьДляИзменения = Истина;
КонецЕсли;


//7 Себестоимость
Движения.Себестоимость.Записывать = Истина;
Движения.Себестоимость.Очистить();



Запрос.Текст ="ВЫБРАТЬ
| ДокТЧ.Номенклатура,
| ДокТЧ.ЕдиницаИзмерения,
| ДокТЧ.Количество,
| ДокТЧ.Склад,
| ЕСТЬNULL(СебестоимостьОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
| СебестоимостьОстатки.Номенклатура.Представление,
| ЕСТЬNULL(СебестоимостьОстатки.СуммаОстаток, 0) КАК ОстатокСум
|ИЗ
| ДокТЧ КАК ДокТЧ
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Себестоимость.Остатки(
| &ТочкаИтогов,
| Номенклатура В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| ДокТЧ.Номенклатура
| ИЗ
| ДокТЧ)) КАК СебестоимостьОстатки
| ПО ДокТЧ.Номенклатура = СебестоимостьОстатки.Номенклатура
| И ДокТЧ.ЕдиницаИзмерения = СебестоимостьОстатки.ЕдиницаИзмерения";

Запрос.Параметры.Вставить("ТочкаИтогов", МоментВремени());

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

КонецЦикла;

КонецПроцедуры

Отчет "Ведомость по складу".
Для вывода отчета в требуемом виде придется вести учет характеристик.
Для этого заведем регистр  сведений "ЗначениеСвойствТоваров" с измерениями "Номенклатура" с признаками "Ведущее " и "Основной отбор" и "свойство" тип "План видов характеристик "Свойства объектов" и ресурс "Значение" Тип "Характеристика.СвойстваОбъектов".
В ПВХ "Свойства объектов" добавим  в тип реквизит"Справочник.Контрагенты" и добавим предопределенное значение "Производитель". Построение отчета не расписываю при желании можно посмотреть скачав решение.
скачать


Посмотреть исправленную версию



2 комментария:

  1. Добрый день. Так и не поняла смысл Вашего отчета, если данные в нем должны формироваться в зависимости от выбранного склада. У Вас же - "одна песня" и на склад "Основной" и на склад "Запасной". Или, может я чего-то не увидела?

    ОтветитьУдалить
  2. Я здесь, чтобы поделиться своим свидетельством о том, что хорошая кредитная компания сделала для меня. Меня зовут Никита Таня, я родом из России, и я прекрасная мама троих детей. Я потеряла деньги, пытаясь получить кредит, это было так тяжело для меня и моих детей, что я зашла в интернет, чтобы получить помощь в кредите, все надежды были потерял до одного верного дня, когда я встретил моего друга, который недавно получил кредит от очень честного человека, мистера Бенджамина. Она познакомила меня с этим честным кредитным агентом, господином Бенджамином, который помог мне получить кредит в течение 5 рабочих дней, я буду вечно благодарен мистеру Бенджамину за то, что он помог мне снова встать на ноги. Вы можете связаться с г-ном Бенджамином по электронной почте: lfdsloans@outlook.com, они не знают, что я делаю это для них, но я просто должен это сделать, потому что многие люди, нуждающиеся в помощи по кредиту, пожалуйста, приходите этому честному человеку, и тебя тоже можно спасти .WhatsApp: (+ 1 989-394-3740)

    ОтветитьУдалить