Распределение серий номенклатуры в соответствии с остатками.
Эксель = Новый 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();
ПоказатьПишу следующую обработку, смысл загрузить заказ а количество товара распределить по сериям, то есть если общего количества на одной серии не хватает, то брал недостающую часть из другой, или удалял строку если нет товара вообще. Сейчас получается полный примитив, не как не могу понять как реализовать алгоритм, помогите плз.
Найденные решения
(8) Получили строку Excel с данными, нашли соответствие номенклатуры, проверили остаток серий по Сумма(КоличествоОстаток), сообщили если что не так, если есть что списывать - создали переменную
Дальше делаем цикл выборки Серий:
ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ; /// если есть корректность формата данных.
Дальше делаем цикл выборки Серий:
Пока СерииНоменклатуры.Следующий() Цикл
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
...
НовСтрока.Количество = ОсталосьРаспределитьКоличествоЗаказ;
ОсталосьРаспределитьКоличествоЗаказ = 0;
Прервать;
Иначе /// У нас по текущей серии остаток меньше, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
...
НовСтрока.Количество = СерииНоменклатуры.КоличествоОстаток;
ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
КонецЦикла;
ПоказатьОстальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(1) А внешними источниками не балуетесь? Через COM привычнее?
По поводу советов. Артикул по оператору ПОДОБНО искать в запросе не очень. Результат будет слишком разнообразный.
И в цикле
Списание серий можно позаимствовать из механизма списания партий.
По поводу советов. Артикул по оператору ПОДОБНО искать в запросе не очень. Результат будет слишком разнообразный.
И в цикле
Пока ВыборкаНоменклатуры.Следующий() Цикл
Номенклатура = ВыборкаНоменклатуры.Ссылка;
КонецЦикла;
у Вас будет прилетать в номенклатуру последнее значение выборки этого прекрасного разнообразия.
Номенклатура = ВыборкаНоменклатуры.Ссылка;
КонецЦикла;
Номенклатура = Справочники.Номенклатура.НайтиПоРеквизиту("Артикул", Артикул);
Так будет проще и быстрее.
Списание серий можно позаимствовать из механизма списания партий.
(3)Можно, но чуть попозже. А Вы пока посмотрите на свой код и попытайтесь оптимизировать запрос, например установить параметры виртуальной таблицы ТоварыНаСкладах.ОстаткиИОбороты и не находить значение параметров по наименованию Справочники.Склады.НайтиПоНаименованию("Главный склад"). Можно сделать реквизит обработки и вывести его на форму. А значение по умолчанию выводить функцией из общего модуля или настроек пользователя.
(3)Интересный набросок, конечно. Не буду спрашивать что Вы делаете с ТЗ "СерииНоменклатуры".
И почему не проверяете функциональную опцию учета по сериям. И почему строку в число, а число в строку.
И почему не задаете организацию параметром в запросе. И почему игнорируете характеристики номенклатуры.
Итак, я вижу пару вариантов учета - это когда серии обязательны и номенклатуры без серий в учете нет, и когда есть номенклатура с сериями и без серий в учете.
А списывать нужно только исключительно по сериям.
Получив соответствие номенклатуры, нужно как можно быстрее проверить достаточно ли остатков. Чтобы не делать дальше лишних движений.
И в варианте когда серии обязательны, проверяется просто остаток по номенклатуре (нам не нужно выбирать серии, они есть везде), а когда серии не обязательны, то проверяется либо агрегатная функция сумма по количеству остатка серий, либо общий итог количества остатка по сериям.
Потом убедившись, что остатка по сериям нам хватит, в цикле выборки по сериям мы проверяем больше ли КоличествоЗаказ чем остаток по строке выборке серий, и если меньше или равно, то устанавливаем нужное количество, добавляем строку и прерываем цикл. В противном случае мы проверяем значение переменной, например ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ (установлена до цикла), которая является разностью между ОсталосьРаспределитьКоличествоЗаказ и количеством остатка по текущей серии в цикле, и продолжаем цикл выборки серий и добавления строк до тех пор, пока значение ОсталосьРаспределитьКоличествоЗаказ не будет равно 0. Потом первый цикл, который перебирает строки Excel возвращает нас к следующей строке из Excel или первый цикл заканчивается и документ записывается.
И почему не проверяете функциональную опцию учета по сериям. И почему строку в число, а число в строку.
И почему не задаете организацию параметром в запросе. И почему игнорируете характеристики номенклатуры.
Итак, я вижу пару вариантов учета - это когда серии обязательны и номенклатуры без серий в учете нет, и когда есть номенклатура с сериями и без серий в учете.
А списывать нужно только исключительно по сериям.
Получив соответствие номенклатуры, нужно как можно быстрее проверить достаточно ли остатков. Чтобы не делать дальше лишних движений.
И в варианте когда серии обязательны, проверяется просто остаток по номенклатуре (нам не нужно выбирать серии, они есть везде), а когда серии не обязательны, то проверяется либо агрегатная функция сумма по количеству остатка серий, либо общий итог количества остатка по сериям.
Потом убедившись, что остатка по сериям нам хватит, в цикле выборки по сериям мы проверяем больше ли КоличествоЗаказ чем остаток по строке выборке серий, и если меньше или равно, то устанавливаем нужное количество, добавляем строку и прерываем цикл. В противном случае мы проверяем значение переменной, например ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ (установлена до цикла), которая является разностью между ОсталосьРаспределитьКоличествоЗаказ и количеством остатка по текущей серии в цикле, и продолжаем цикл выборки серий и добавления строк до тех пор, пока значение ОсталосьРаспределитьКоличествоЗаказ не будет равно 0. Потом первый цикл, который перебирает строки Excel возвращает нас к следующей строке из Excel или первый цикл заканчивается и документ записывается.
(8) Получили строку Excel с данными, нашли соответствие номенклатуры, проверили остаток серий по Сумма(КоличествоОстаток), сообщили если что не так, если есть что списывать - создали переменную
Дальше делаем цикл выборки Серий:
ОсталосьРаспределитьКоличествоЗаказ = КоличествоЗаказ; /// если есть корректность формата данных.
Дальше делаем цикл выборки Серий:
Пока СерииНоменклатуры.Следующий() Цикл
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
...
НовСтрока.Количество = ОсталосьРаспределитьКоличествоЗаказ;
ОсталосьРаспределитьКоличествоЗаказ = 0;
Прервать;
Иначе /// У нас по текущей серии остаток меньше, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
...
НовСтрока.Количество = СерииНоменклатуры.КоличествоОстаток;
ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
КонецЦикла;
Показать КоличествоПоУчетуСтрока = Строка(ВыборкаСерийколичество);
КоличествоФактСтрока = Строка(КоличествоЗаказ);
КоличествоПоУчету = Число(КоличествоПоУчетуСтрока);
КоличествоФакт = Число(КоличествоЗаказ);
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
НовСтрока.ВариантОбеспечения = Перечисления.ВариантыОбеспечения.Отгрузить;
НовСтрока.ДатаОтгрузки = ТекущаяДата();
НовСтрока.СтатусУказанияСерий = КоличествоЗаказ;
НовСтрока.Серия = СерииНоменклатуры;
Если КоличествоПоУчету < КоличествоФакт Тогда
Сообщить("На складе отсутствует необходимое количество"+" "+Номенклатура+" "+КоличествоЗаказ+"Шт."" "+"Будет списано"+" "+КоличествоПоУчету+"Шт.");
НовСтрока.Количество = КоличествоПоУчету;
НовСтрока.КоличествоУпаковок = КоличествоПоУчету;
ИначеЕсли КоличествоПоУчету = 0 Тогда
Сообщить("Отсутствует полностью"+""+Номенклатура);
НовСтрока.Количество = 0;
НовСтрока.КоличествоУпаковок = 0;
ИначеЕсли КоличествоПоУчету > КоличествоФакт Тогда
Сообщить("Распределено в соответствии с заказом"+Номенклатура+" "+КоличествоФакт+"Шт." );
НовСтрока.Количество = КоличествоФакт;
НовСтрока.КоличествоУпаковок = КоличествоФакт;
КонецЕсли;
НовСтрока.Цена = Цена;
НовСтрока.СтавкаНДС = Перечисления.СтавкиНДС.БезНДС;
НовСтрока.Сумма = ТоталSumma;
КонецЦикла;
ПоказатьЭто получается вместо этого куска??
Если ОсталосьРаспределитьКоличествоЗаказ <= СерииНоменклатуры.КоличествоОстаток Тогда /// У нас по текущей серии остаток больше или равен, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
НовСтрока.СтатусУказанияСерий = КоличествоЗаказ;
НовСтрока.Серия = СерииНоменклатуры.Ссылка;
НовСтрока.Количество = ОсталосьРаспределитьКоличествоЗаказ;
НовСтрока.КоличествоУпаковок = ОсталосьРаспределитьКоличествоЗаказ;
ОсталосьРаспределитьКоличествоЗаказ = 0;
Прервать;
Иначе /// У нас по текущей серии остаток меньше, чем нужно по заказу
НовСтрока = Заказ.Товары.Добавить();
НовСтрока.Номенклатура = Номенклатура;
НовСтрока.Серия = СерииНоменклатуры.Ссылка;
НовСтрока.СтатусУказанияСерий = КоличествоЗаказ;
НовСтрока.Количество = СерииНоменклатуры.КоличествоОстаток;
НовСтрока.КоличествоУпаковок = СерииНоменклатуры.КоличествоОстаток;
ОсталосьРаспределитьКоличествоЗаказ = ОсталосьРаспределитьКоличествоЗаказ - СерииНоменклатуры.КоличествоОстаток;
КонецЕсли;
ПоказатьДа, замечательно, только вот серию саму не подставляет.
Делал что-то похожее для характеристик, которые используются как партии.
Получал остатки по номенклатуре. Делал 2 таблицы, что нужно распределить и что распределено. Потом по остаткам сравнивались таблицы, чего не хватало записывал под спец характеристику.
Но я это делал кодом. Посмотри у Чистова он это делает запросом!
Получал остатки по номенклатуре. Делал 2 таблицы, что нужно распределить и что распределено. Потом по остаткам сравнивались таблицы, чего не хватало записывал под спец характеристику.
Но я это делал кодом. Посмотри у Чистова он это делает запросом!
Внимание! Тема сдана в архив
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот