Имя: Пароль:
1C
1С v8
Задача 8 опер учет
0 Pandoch
 
14.06.15
15:50
Доброго времени суток! Осмелюсь побеспокоить всех  своими смертными проблемами - решаю задачку 1.8 по 8.3, на форуме Чистова не дождешься в наши времена уже ответов и комментариев, поэтому на обозрение и критику выкладываю свое решение сюда (обработка проведения Расходной накладной). Если у кого будет желание - буду рада комментариям!

P.S. По-моему, довольно громоздко вышло в проведении расходной, можно конечно запрос по табличной части документа вынести вверх в менеджер временных таблиц, но может еще как-то можно оптимизировать.


текст задачи:
Закупка товара происходит только в отдел закупок, а непосредственно продажа
происходит в торговых точках.
Перемещение товара происходит по трансфертной цене и также
отражается документом «Расходная накладная», при этом цена продажи не
указывается. Товар может перемещаться только из отдела закупок в торговую
точку. Трансфертная цена определяется как себестоимость перемещаемого
товара, увеличенная на процент наценки, задаваемый для каждой торговой точки.
При продаже товара необходимо в первую очередь контролировать хватает
ли товара в данной торговой точке. Если нет – необходимо программно создать
документ по перемещению недостающего товара из отдела закупок. В том случае,
когда и в отделе закупок товара не хватает, документ для перемещения не
создается, а продажа не производится (документ не проводится).
Себестоимость товаров рассчитывается как средняя по отделу.

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

        
        //документ перемещения товаров с отдела закупок в торговые точки
        движения.ОстаткиНоменклатуры.Записывать = Истина;
        Движения.ОстаткиНоменклатуры.Очистить();
        Движения.ОстаткиНоменклатуры.Записать();
        
        блокировка = новый БлокировкаДанных;
        элем = блокировка.Добавить("регистрНакопления.ОстаткиНоменклатуры");
        элем.Режим = РежимБлокировкиДанных.Исключительный;
        элем.ИсточникДанных = СписокНоменклатуры;
        элем.ИспользоватьИзИсточникаДанных("номенклатура", "номенклатура");
        элем.УстановитьЗначение("Отдел", ОтделЗакупок);
        блокировка.Заблокировать();
        
        запрос = новый запрос("ВЫБРАТЬ
                              |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
                              |    СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество
                              |ПОМЕСТИТЬ Перемещать
                              |ИЗ
                              |    Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
                              |ГДЕ
                              |    РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &ссылка
                              |
                              |СГРУППИРОВАТЬ ПО
                              |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура
                              |
                              |ИНДЕКСИРОВАТЬ ПО
                              |    Номенклатура
                              |;
                              |
                              |////////////////////////////////////////////////////////////////////////////////
                              |ВЫБРАТЬ
                              |    Перемещать.Номенклатура,
                              |    Перемещать.Количество,
                              |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
                              |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ОстатокСумма
                              |ИЗ
                              |    Перемещать КАК Перемещать
                              |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
                              |                &моментВремени,
                              |                Номенклатура В
                              |                        (ВЫБРАТЬ
                              |                            перемещать.номенклатура
                              |                        ИЗ
                              |                            перемещать)
                              |                    И Отдел = &отделЗакупок) КАК ОстаткиНоменклатурыОстатки
                              |        ПО Перемещать.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура");
                              
        запрос.УстановитьПараметр("ссылка", ссылка);
        запрос.УстановитьПараметр("отделЗакупок", ОтделЗакупок);
        запрос.УстановитьПараметр("моментВремени", МоментВремени());
        результат = запрос.Выполнить();
        Если не результат.Пустой()тогда
            
            выборка = результат.Выбрать();
            Пока выборка.Следующий() цикл
                
                Если выборка.количество > ВЫБОРКА.ОстатокКол тОГДА
                    Соо = новый СообщениеПользователю;
                    соо.Текст = "Не хватает " + выборка.номенклатура + " для перемещения с отдела закупок! Требуется " +
                        выборка.количество + ", доступно: " + ВЫБОРКА.ОстатокКол + ".";
                    соо.Сообщить();
                    отказ = Истина;
                    Продолжить;
                КонецЕсли;    
                    
                Если отказ Тогда
                    Продолжить;
                КонецЕсли;
                
                ДвижРасх = Движения.ОстаткиНоменклатуры.Добавить();
                ДвижРасх.Период = дата;
                ДвижРасх.ВидДвижения = ВидДвиженияНакопления.Расход;
                ДвижРасх.Отдел = ОтделЗакупок;
                ДвижРасх.Номенклатура = выборка.номенклатура;
                ДвижРасх.Количество = выборка.Количество;
                ДвижРасх.сумма = ?(выборка.Количество = ВЫБОРКА.ОстатокКол, ВЫБОРКА.ОстатокСумма, окр(выборка.Количество/ВЫБОРКА.ОстатокКол,2)*выборка.ОстатокСумма);
                
                ДвижРасх = Движения.ОстаткиНоменклатуры.Добавить();
                ДвижРасх.Период = дата;
                ДвижРасх.ВидДвижения = ВидДвиженияНакопления.Приход;
                ДвижРасх.Отдел = ТорговаяТочка;
                ДвижРасх.Номенклатура = выборка.номенклатура;
                ДвижРасх.Количество = выборка.Количество;
                ДвижРасх.сумма = ?(выборка.Количество = ВЫБОРКА.ОстатокКол, ВЫБОРКА.ОстатокСумма*(1+Наценка/100), окр(выборка.Количество/ВЫБОРКА.ОстатокКол,2)*выборка.ОстатокСумма*(1+Наценка/100));
                
            КонецЦикла;
        КонецЕсли;
        
    Иначе
        //операция продажи с торговой точки
        //документ перемещения товаров с отдела закупок в торговые точки
        движения.ОстаткиНоменклатуры.Записывать = Истина;
        Движения.ОстаткиНоменклатуры.Очистить();
        Движения.ОстаткиНоменклатуры.Записать();
        
        блокировка = новый БлокировкаДанных;
        элем = блокировка.Добавить("регистрНакопления.ОстаткиНоменклатуры");
        элем.Режим = РежимБлокировкиДанных.Исключительный;
        элем.ИсточникДанных = СписокНоменклатуры;
        элем.ИспользоватьИзИсточникаДанных("номенклатура", "номенклатура");
        элем.УстановитьЗначение("Отдел", ОтделЗакупок);
        
        элем = блокировка.Добавить("регистрНакопления.ОстаткиНоменклатуры");
        элем.Режим = РежимБлокировкиДанных.Исключительный;
        элем.ИсточникДанных = СписокНоменклатуры;
        элем.ИспользоватьИзИсточникаДанных("номенклатура", "номенклатура");
        элем.УстановитьЗначение("Отдел", ТорговаяТочка);
        блокировка.Заблокировать();
        
        запрос = новый запрос("ВЫБРАТЬ
                              |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
                              |    СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество
                              |ПОМЕСТИТЬ Перемещать
                              |ИЗ
                              |    Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
                              |ГДЕ
                              |    РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &ссылка
                              |
                              |СГРУППИРОВАТЬ ПО
                              |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура
                              |
                              |ИНДЕКСИРОВАТЬ ПО
                              |    Номенклатура
                              |;
                              |
                              |////////////////////////////////////////////////////////////////////////////////
                              |ВЫБРАТЬ
                              |    Перемещать.Номенклатура,
                              |    Перемещать.Количество,
                              |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
                              |    ОстаткиНоменклатурыОстатки.Отдел
                              |ПОМЕСТИТЬ ОстаткиВДвухОтделах
                              |ИЗ
                              |    Перемещать КАК Перемещать
                              |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
                              |                &моментВремени,
                              |                Номенклатура В
                              |                        (ВЫБРАТЬ
                              |                            перемещать.Номенклатура
                              |                        ИЗ
                              |                            перемещать)
                              |                    И Отдел = &отделЗакупок) КАК ОстаткиНоменклатурыОстатки
                              |        ПО Перемещать.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
                              |
                              |ОБЪЕДИНИТЬ ВСЕ
                              |
                              |ВЫБРАТЬ
                              |    Перемещать.Номенклатура,
                              |    Перемещать.Количество,
                              |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0),
                              |    ОстаткиНоменклатурыОстатки.Отдел
                              |ИЗ
                              |    Перемещать КАК Перемещать
                              |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
                              |                &моментВремени,
                              |                Номенклатура В
                              |                        (ВЫБРАТЬ
                              |                            перемещать.Номенклатура
                              |                        ИЗ
                              |                            перемещать)
                              |                    И Отдел = &ТорговаяТочка) КАК ОстаткиНоменклатурыОстатки
                              |        ПО Перемещать.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
                              |;
                              |
                              |////////////////////////////////////////////////////////////////////////////////
                              |ВЫБРАТЬ
                              |    ОстаткиВДвухОтделах.Номенклатура КАК Номенклатура,
                              |    ОстаткиВДвухОтделах.Количество КАК Количество,
                              |    ОстаткиВДвухОтделах.ОстатокКол КАК ОстатокКол,
                              |    ОстаткиВДвухОтделах.Отдел
                              |ИЗ
                              |    ОстаткиВДвухОтделах КАК ОстаткиВДвухОтделах
                              |ИТОГИ
                              |    МАКСИМУМ(Количество),
                              |    СУММА(ОстатокКол)
                              |ПО
                              |    Номенклатура");
                              
        запрос.УстановитьПараметр("ссылка", ссылка);
        запрос.УстановитьПараметр("отделЗакупок", ОтделЗакупок);
        запрос.УстановитьПараметр("Торговаяточка", ТорговаяТочка);
        запрос.УстановитьПараметр("моментВремени", МоментВремени());
        результат = запрос.Выполнить();
        Если не результат.Пустой() Тогда
            Выборкапономенклатуре = результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
            
            создаватьПеремещение = ложь;
            таблицаТоваров = новый ТаблицаЗначений;
            таблицаТоваров.Колонки.Добавить("Номенклатура");
            таблицаТоваров.Колонки.Добавить("Количество");
            Пока выборкапономенклатуре.Следующий() цикл
                Если выборкапономенклатуре.Количество > выборкапономенклатуре.ОстатокКол Тогда
                    Соо = новый СообщениеПользователю;
                    соо.Текст = "Не хватает " + выборкапономенклатуре.номенклатура + "! Требуется " +
                        выборкапономенклатуре.количество + ", доступно на торговой точке и в отделе закупок: " +
                        выборкапономенклатуре.ОстатокКол + ".";
                    соо.Сообщить();
                    отказ = Истина;
                КонецЕсли;
                
                Если отказ тогда
                    Продолжить;
                КонецЕсли;
                
                ВыборкаДеталь = Выборкапономенклатуре.Выбрать();
                пока ВыборкаДеталь.Следующий() цикл
                    Если ВыборкаДеталь.отдел = ТорговаяТочка Тогда
                        ПоТорговойТочке = ВыборкаДеталь.ОстатокКол;
                    КонецЕсли;
                КонецЦикла;
                //проверяем, нужно ли по данной номенклатуре делать перемещение
                Если ПоТорговойТочке < выборкапономенклатуре.Количество Тогда
                    создаватьПеремещение = Истина;
                    стр = таблицаТоваров.Добавить();
                    стр.Номенклатура = выборкапономенклатуре.номенклатура;
                    стр.количество = выборкапономенклатуре.Количество - ПоТорговойТочке;
                КонецЕсли;
            КонецЦикла;
            
            Если не отказ и создаватьПеремещение Тогда
                докПерем = документы.РасходнаяНакладная.СоздатьДокумент();
                докПерем.Дата = дата - 60;
                докПерем.СписокНоменклатуры.Загрузить(таблицаТоваров);
                докПерем.ТорговаяТочка = ТорговаяТочка;
                докПерем.Перемещение = Истина;
                докПерем.Записать(РежимЗаписиДокумента.Проведение);
            КонецЕсли;
            
            Если не отказ Тогда
                //непосредственно списание - все товары доступны, перемещение создано, если требовалось
                //запрос делаем еще раз чтобы получить данные (суммы) на торговой точке обновленные
                запрос = новый запрос("ВЫБРАТЬ
                                      |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
                                      |    СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество
                                      |ПОМЕСТИТЬ Перемещать
                                      |ИЗ
                                      |    Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
                                      |ГДЕ
                                      |    РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &ссылка
                                      |
                                      |СГРУППИРОВАТЬ ПО
                                      |    РасходнаяНакладнаяСписокНоменклатуры.Номенклатура
                                      |
                                      |ИНДЕКСИРОВАТЬ ПО
                                      |    Номенклатура
                                      |;
                                      |
                                      |////////////////////////////////////////////////////////////////////////////////
                                      |ВЫБРАТЬ
                                      |    Перемещать.Номенклатура,
                                      |    Перемещать.Количество,
                                      |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
                                      |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ОстатокСумма
                                      |ИЗ
                                      |    Перемещать КАК Перемещать
                                      |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
                                      |                &моментВремени,
                                      |                Номенклатура В
                                      |                        (ВЫБРАТЬ
                                      |                            перемещать.Номенклатура
                                      |                        ИЗ
                                      |                            перемещать)
                                      |                    И Отдел = &ТорговаяТочка) КАК ОстаткиНоменклатурыОстатки
                                      |        ПО Перемещать.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура");
                
                запрос.УстановитьПараметр("ссылка", ссылка);
                запрос.УстановитьПараметр("Торговаяточка", ТорговаяТочка);
                запрос.УстановитьПараметр("моментВремени", МоментВремени());
                выборка = запрос.Выполнить().выбрать();
                пока выборка.Следующий() цикл
                    ДвижРасх = Движения.ОстаткиНоменклатуры.Добавить();
                    ДвижРасх.Период = дата;
                    ДвижРасх.ВидДвижения = ВидДвиженияНакопления.Расход;
                    ДвижРасх.Отдел = ТорговаяТочка;
                    ДвижРасх.Номенклатура = выборка.номенклатура;
                    ДвижРасх.Количество = выборка.Количество;
                    //сумма списывается с учетом наценки
              &nbs
1 GROOVY
 
14.06.15
16:22
Вопросы нормальные надо задавать - тогда дождешся.
2 Pandoch
 
14.06.15
16:47
нуу, правильно ли в решении использованы блокировки?
Кaк может человек ожидaть, что его мольбaм о снисхождении ответит тот, кто превыше, когдa сaм он откaзывaет в милосердии тем, кто ниже его? Петр Трубецкой