Распределение серий номенклатуры в соответствии с остатками.

1. progaoff 16.07.18 17:10 Сейчас в теме
	
	Эксель = Новый COMОбъект("Excel.Application");
	Книга = Эксель.WorkBooks.Open(ИмяФайла);
	Лист = Книга.WorkSheets(1);
	ВсегоСтрок = Лист.Cells(1,1).SpecialCells(11).Row;
	
	
	Заказ                 = Документы.ЗаказКлиента.СоздатьДокумент();
	Заказ.Дата            = ТекущаяДата();
	Заказ.Организация     = Справочники.Организации.НайтиПоНаименованию("ИП");
	Заказ.Склад           = Справочники.Склады.НайтиПоНаименованию("Главный склад");
	Заказ.ДатаОтгрузки    = ТекущаяДата();
	Заказ.Статус          = Перечисления.СтатусыЗаказовКлиентов.КОтгрузке;
	Заказ.ЦенаВключаетНДС = Истина;
	Заказ.ЦенаВключаетНДС	 = Истина;
	    Для Стр = 2 По ВсегоСтрок Цикл
		КоличествоСтр = СокрЛП(Лист.Cells(Стр,5).Value);
		Попытка
			Количество = Число(КоличествоСтр);
		Исключение
			Если КоличествоСтр = "" Тогда
				Продолжить;
			Иначе
				Количество = 0;
			КонецЕсли;
		КонецПопытки;
        
		Артикул 		  = СокрЛП(Лист.Cells(Стр, КолонкаАртикул).Value);
		КоличествоЗаказ   = Число(Лист.Cells(Стр, КолонкаКоличество).Value);
		Цена 			  = Число(Лист.Cells(Стр, КолонкаЦена).Value);
		ТоталSumma		  = СокрЛП(Лист.Cells(Стр, КолонкаСумма).Value);
		
		ЗапросНоменклатура = Новый Запрос;
		ЗапросНоменклатура.Текст = "ВЫБРАТЬ
		               |	Номенклатура.Ссылка
		               |ИЗ
		               |	Справочник.Номенклатура КАК Номенклатура
		               |ГДЕ
		               |	Номенклатура.Артикул ПОДОБНО &АртикулЦифры";
	
		
		
		
		ЗапросНоменклатура.УстановитьПараметр("АртикулЦифры", Артикул);
		ВыборкаНоменклатуры = ЗапросНоменклатура.Выполнить().Выбрать();	
		Номенклатура = Справочники.Номенклатура.ПустаяСсылка();
		Пока ВыборкаНоменклатуры.Следующий() Цикл	
			Номенклатура = ВыборкаНоменклатуры.Ссылка;
		КонецЦикла;
		НоменклатураСерий =  ЗапросНоменклатура.Выполнить().Выгрузить();
		ЗапросСерии = Новый Запрос;
		ЗапросСерии.Текст =  "ВЫБРАТЬ
		                     |	ТоварыНаСкладахОстаткиИОбороты.Серия.Ссылка КАК Ссылка,
		                     |	МИНИМУМ(ТоварыНаСкладахОстаткиИОбороты.Серия.ГоденДо) КАК СерияГоденДо,
		                     |	ЕСТЬNULL(ТоварыНаСкладахОстаткиИОбороты.ВНаличииКонечныйОстаток, 0) КАК КоличествоОстаток
		                     |ИЗ
		                     |	РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(, , , , ) КАК ТоварыНаСкладахОстаткиИОбороты
		                     |ГДЕ
		                     |	ТоварыНаСкладахОстаткиИОбороты.Номенклатура В(&Номенклатура)
		                     |	И ТоварыНаСкладахОстаткиИОбороты.Склад = &Склад
		                     |	И НЕ ТоварыНаСкладахОстаткиИОбороты.Серия.Ссылка = НЕОПРЕДЕЛЕНО
		                     |
		                     |СГРУППИРОВАТЬ ПО
		                     |	ТоварыНаСкладахОстаткиИОбороты.Серия.Ссылка,
		                     |	ЕСТЬNULL(ТоварыНаСкладахОстаткиИОбороты.ВНаличииКонечныйОстаток, 0)
		                     |
		                     |УПОРЯДОЧИТЬ ПО
		                     |	СерияГоденДо";
		ЗапросСерии.УстановитьПараметр("Номенклатура",Номенклатура);	
		ЗапросСерии.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоНаименованию("Главный склад"));
	

		СерииНоменклатуры = ЗапросСерии.Выполнить().Выбрать();
		ВыборкаСерий = Справочники.СерииНоменклатуры.ПустаяСсылка();
		Пока СерииНоменклатуры.Следующий() Цикл
			ВыборкаСерий = СерииНоменклатуры.Ссылка;
			ВыборкаСерийколичество = СерииНоменклатуры.КоличествоОстаток;
		КонецЦикла;
					
		КоличествоПоУчетуСтрока = Строка(ВыборкаСерийколичество);
		КоличествоФактСтрока    = Строка(КоличествоЗаказ);
		КоличествоПоУчету		= Число(КоличествоПоУчетуСтрока);
		КоличествоФакт          = Число(КоличествоЗаказ);
		НовСтрока = Заказ.Товары.Добавить();
		НовСтрока.Номенклатура        = Номенклатура;
		НовСтрока.ВариантОбеспечения  = Перечисления.ВариантыОбеспечения.Отгрузить;
		НовСтрока.ДатаОтгрузки		  = ТекущаяДата();
		НовСтрока.СтатусУказанияСерий = КоличествоЗаказ;
		НовСтрока.Серия               = СерииНоменклатуры;
	Если  КоличествоПоУчету < КоличествоФакт Тогда
		Сообщить("На складе отсутствует необходимое количество"+" "+Номенклатура+" "+КоличествоЗаказ+"Шт."" "+"Будет списано"+" "+КоличествоПоУчету+"Шт.");
		НовСтрока.Количество          = КоличествоПоУчету;
		НовСтрока.КоличествоУпаковок  = КоличествоПоУчету;
	ИначеЕсли КоличествоПоУчету = 0   Тогда
		Сообщить("Отсутствует полностью"+""+Номенклатура);
		НовСтрока.Количество          = 0;
		НовСтрока.КоличествоУпаковок  = 0;
	ИначеЕсли КоличествоПоУчету > КоличествоФакт Тогда
		Сообщить("Распределено в соответствии с заказом"+Номенклатура+" "+КоличествоФакт+"Шт." );
		НовСтрока.Количество          = КоличествоФакт;
		НовСтрока.КоличествоУпаковок  = КоличествоФакт;
		
	КонецЕсли;	
		НовСтрока.Цена				  = Цена;
		НовСтрока.СтавкаНДС 		  = Перечисления.СтавкиНДС.БезНДС;
		НовСтрока.Сумма               = ТоталSumma; 
	КонецЦикла;
	
	Заказ.Записать(РежимЗаписиДокумента.Запись);
		
	Эксель.Application.Quit();	
	
Показать


Пишу следующую обработку, смысл загрузить заказ а количество товара распределить по сериям, то есть если общего количества на одной серии не хватает, то брал недостающую часть из другой, или удалял строку если нет товара вообще. Сейчас получается полный примитив, не как не могу понять как реализовать алгоритм, помогите плз.
Найденные решения
9. Leon75 17.07.18 13:02 Сейчас в теме
(8) Получили строку Excel с данными, нашли соответствие номенклатуры, проверили остаток серий по Сумма(КоличествоОстаток), сообщили если что не так, если есть что списывать - создали переменную
ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ; /// если есть корректность формата данных. 


Дальше делаем цикл выборки Серий:

Пока СерииНоменклатуры.Следующий() Цикл 
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда  /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
 НовСтрока = Заказ.Товары.Добавить();
 НовСтрока.Номенклатура  = Номенклатура;
...
 НовСтрока.Количество = ОсталосьРаспределитьКоличествоЗаказ;
ОсталосьРаспределитьКоличествоЗаказ = 0;
Прервать;
Иначе  /// У нас по текущей серии остаток меньше, чем нужно по заказу
 НовСтрока = Заказ.Товары.Добавить();
 НовСтрока.Номенклатура  = Номенклатура;
...
 НовСтрока.Количество = СерииНоменклатуры.КоличествоОстаток;
ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
КонецЦикла;
Показать
Остальные ответы
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
2. Leon75 16.07.18 17:44 Сейчас в теме
(1) А внешними источниками не балуетесь? Через COM привычнее?
По поводу советов. Артикул по оператору ПОДОБНО искать в запросе не очень. Результат будет слишком разнообразный.
И в цикле
Пока ВыборкаНоменклатуры.Следующий() Цикл
Номенклатура = ВыборкаНоменклатуры.Ссылка;
КонецЦикла;
у Вас будет прилетать в номенклатуру последнее значение выборки этого прекрасного разнообразия.
Номенклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул);
Так будет проще и быстрее.
Списание серий можно позаимствовать из механизма списания партий.
3. progaoff 16.07.18 18:03 Сейчас в теме
(2) COM по тому что эксель.
На счет списания партий, можно уточнить? Забыл сказать имеем УТ 11.4
4. Leon75 16.07.18 19:28 Сейчас в теме
(3)Можно, но чуть попозже. А Вы пока посмотрите на свой код и попытайтесь оптимизировать запрос, например установить параметры виртуальной таблицы ТоварыНаСкладах.ОстаткиИОбороты и не находить значение параметров по наименованию Справочники.Склады.НайтиПоНаименованию("Главный склад"). Можно сделать реквизит обработки и вывести его на форму. А значение по умолчанию выводить функцией из общего модуля или настроек пользователя.
5. progaoff 17.07.18 11:26 Сейчас в теме
(4) Да, этот момент я переделал.
6. Leon75 17.07.18 11:34 Сейчас в теме
(3)Интересный набросок, конечно. Не буду спрашивать что Вы делаете с ТЗ "СерииНоменклатуры".
И почему не проверяете функциональную опцию учета по сериям. И почему строку в число, а число в строку.
И почему не задаете организацию параметром в запросе. И почему игнорируете характеристики номенклатуры.

Итак, я вижу пару вариантов учета - это когда серии обязательны и номенклатуры без серий в учете нет, и когда есть номенклатура с сериями и без серий в учете.
А списывать нужно только исключительно по сериям.
Получив соответствие номенклатуры, нужно как можно быстрее проверить достаточно ли остатков. Чтобы не делать дальше лишних движений.
И в варианте когда серии обязательны, проверяется просто остаток по номенклатуре (нам не нужно выбирать серии, они есть везде), а когда серии не обязательны, то проверяется либо агрегатная функция сумма по количеству остатка серий, либо общий итог количества остатка по сериям.

Потом убедившись, что остатка по сериям нам хватит, в цикле выборки по сериям мы проверяем больше ли КоличествоЗаказ чем остаток по строке выборке серий, и если меньше или равно, то устанавливаем нужное количество, добавляем строку и прерываем цикл. В противном случае мы проверяем значение переменной, например ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ (установлена до цикла), которая является разностью между ОсталосьРаспределитьКоличествоЗаказ и количеством остатка по текущей серии в цикле, и продолжаем цикл выборки серий и добавления строк до тех пор, пока значение ОсталосьРаспределитьКоличествоЗаказ не будет равно 0. Потом первый цикл, который перебирает строки Excel возвращает нас к следующей строке из Excel или первый цикл заканчивается и документ записывается.
7. progaoff 17.07.18 11:56 Сейчас в теме
(6) да, к сожалению, товары без серий присутствуют в учёте. Характеристики, по тому что не веду по ним учет.
8. progaoff 17.07.18 12:16 Сейчас в теме
(6) Ну на счет сравнения количества это понятно, проблема с что сравнивать и в какой конструкции должен быть цикл, вот этого я не понимаю.
9. Leon75 17.07.18 13:02 Сейчас в теме
(8) Получили строку Excel с данными, нашли соответствие номенклатуры, проверили остаток серий по Сумма(КоличествоОстаток), сообщили если что не так, если есть что списывать - создали переменную
ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ; /// если есть корректность формата данных. 


Дальше делаем цикл выборки Серий:

Пока СерииНоменклатуры.Следующий() Цикл 
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда  /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
 НовСтрока = Заказ.Товары.Добавить();
 НовСтрока.Номенклатура  = Номенклатура;
...
 НовСтрока.Количество = ОсталосьРаспределитьКоличествоЗаказ;
ОсталосьРаспределитьКоличествоЗаказ = 0;
Прервать;
Иначе  /// У нас по текущей серии остаток меньше, чем нужно по заказу
 НовСтрока = Заказ.Товары.Добавить();
 НовСтрока.Номенклатура  = Номенклатура;
...
 НовСтрока.Количество = СерииНоменклатуры.КоличествоОстаток;
ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
КонецЦикла;
Показать
15. progaoff 17.07.18 16:42 Сейчас в теме
16. Leon75 17.07.18 16:51 Сейчас в теме
10. progaoff 17.07.18 13:44 Сейчас в теме
 КоличествоПоУчетуСтрока = Строка(ВыборкаСерийколичество);
        КоличествоФактСтрока    = Строка(КоличествоЗаказ);
        КоличествоПоУчету        = Число(КоличествоПоУчетуСтрока);
        КоличествоФакт          = Число(КоличествоЗаказ);
        НовСтрока = Заказ.Товары.Добавить();
        НовСтрока.Номенклатура        = Номенклатура;
        НовСтрока.ВариантОбеспечения  = Перечисления.ВариантыОбеспечения.Отгрузить;
        НовСтрока.ДатаОтгрузки          = ТекущаяДата();
        НовСтрока.СтатусУказанияСерий = КоличествоЗаказ;
        НовСтрока.Серия               = СерииНоменклатуры;
    Если  КоличествоПоУчету < КоличествоФакт Тогда
        Сообщить("На складе отсутствует необходимое количество"+" "+Номенклатура+" "+КоличествоЗаказ+"Шт."" "+"Будет списано"+" "+КоличествоПоУчету+"Шт.");
        НовСтрока.Количество          = КоличествоПоУчету;
        НовСтрока.КоличествоУпаковок  = КоличествоПоУчету;
    ИначеЕсли КоличествоПоУчету = 0   Тогда
        Сообщить("Отсутствует полностью"+""+Номенклатура);
        НовСтрока.Количество          = 0;
        НовСтрока.КоличествоУпаковок  = 0;
    ИначеЕсли КоличествоПоУчету > КоличествоФакт Тогда
        Сообщить("Распределено в соответствии с заказом"+Номенклатура+" "+КоличествоФакт+"Шт." );
        НовСтрока.Количество          = КоличествоФакт;
        НовСтрока.КоличествоУпаковок  = КоличествоФакт;
        
    КонецЕсли;    
        НовСтрока.Цена                  = Цена;
        НовСтрока.СтавкаНДС           = Перечисления.СтавкиНДС.БезНДС;
        НовСтрока.Сумма               = ТоталSumma; 
    КонецЦикла;
Показать


Это получается вместо этого куска??
11. Leon75 17.07.18 14:36 Сейчас в теме
(10)Почти. Проверку по остатку серий и вывод сообщений нужно делать до моего кода.
12. progaoff 17.07.18 15:19 Сейчас в теме
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда  /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
 					 НовСтрока = Заказ.Товары.Добавить();
                     НовСтрока.Номенклатура  		= Номенклатура;
					 НовСтрока.СтатусУказанияСерий  = КоличествоЗаказ;
					 НовСтрока.Серия         		= СерииНоменклатуры.Ссылка;
                     НовСтрока.Количество    		= ОсталосьРаспределитьКоличествоЗаказ;
					 НовСтрока.КоличествоУпаковок   = ОсталосьРаспределитьКоличествоЗаказ;

                     ОсталосьРаспределитьКоличествоЗаказ = 0;
                     Прервать;
                Иначе  /// У нас по текущей серии остаток меньше, чем нужно по заказу
                     НовСтрока = Заказ.Товары.Добавить();
                     НовСтрока.Номенклатура 		 = Номенклатура;
    			     НовСтрока.Серия                 = СерииНоменклатуры.Ссылка;
					 НовСтрока.СтатусУказанияСерий   = КоличествоЗаказ;
                     НовСтрока.Количество			 = СерииНоменклатуры.КоличествоОстаток;
					 НовСтрока.КоличествоУпаковок    = СерииНоменклатуры.КоличествоОстаток;

                     ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
Показать


Да, замечательно, только вот серию саму не подставляет.
13. Xershi 1474 17.07.18 15:27 Сейчас в теме
Делал что-то похожее для характеристик, которые используются как партии.

Получал остатки по номенклатуре. Делал 2 таблицы, что нужно распределить и что распределено. Потом по остаткам сравнивались таблицы, чего не хватало записывал под спец характеристику.

Но я это делал кодом. Посмотри у Чистова он это делает запросом!
14. progaoff 17.07.18 15:28 Сейчас в теме
Все, там же еще статус указания присутствует, который явно не такой как у меня в количестве товара.
Оставьте свое сообщение
Вакансии
1С аналитик
Москва
зарплата от 210 000 руб.
Полный день

Руководитель направления 1С
Москва
зарплата от 350 000 руб.
Полный день

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)