|
Сборка товаров | ☑ | ||
---|---|---|---|---|
0
Rumpil
23.03.12
✎
18:25
|
У меня существует три таблицы: остатки деталей, возможные товары к сборке и остаток деталей после сборки.
Для большего понимания возьмем пример. У меня есть 4 детали - Д1 в количестве 3 шт., Д2 в количестве 4 шт., Д3 в количестве 5 шт., Д4 остаток которой равен нулю. Есть 2 товара, Т1 и Т2. Т1 состоит из Д1 в количестве 1 шт., Д2 в количестве 1 шт и Д3 в количестве 1 шт., а Т2 состоит из Д2 в количестве 1 шт. и Д4 в количестве 1 шт. Существует кнопка "Заполнить таблицы данными". Краткое описание действия кнопки и потом код: При нажатии кнопка таблица "остатки деталей" заполняется остатками деталей, таблица "остаток деталей после сборки" тоже заполняется такими же данными (данная таблица является динамической и каждый раз по мере потенциальной сборки товаров остатки в ней обновляются с учетом собранных потенциально товаров). Вот код: //Заполняю таблицу остатков и динамическую таблицу текущими остатков деталей ВидТовара = Справочники.ВидыНоменклатуры.ПАКЕТ; Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ТоварыНаСкладахОстаткиИОбороты.Номенклатура, | ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток |ИЗ | РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты КАК ТоварыНаСкладахОстаткиИОбороты |ГДЕ | ТоварыНаСкладахОстаткиИОбороты.Склад = &ТекСклад | И ТоварыНаСкладахОстаткиИОбороты.Номенклатура.ВидНоменклатуры = &ВидТовара" ; Запрос.УстановитьПараметр("ТекСклад", Склад); Запрос.УстановитьПараметр("ВидТовара", ВидТовара); Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл НоваяСтрока = Юните.Добавить(); НоваяСтрока.Юните = Выборка.Номенклатура; НоваяСтрока.Количество = Выборка.КоличествоКонечныйОстаток; НоваяСтрока2 = Динамика.Добавить(); НоваяСтрока2.Юните = Выборка.Номенклатура; НоваяСтрока2.Количество = Выборка.КоличествоКонечныйОстаток; КонецЦикла; Далее начинается переборка всех товаров на возможность сборки - считываются комплектующие(детали) товаров и проверяется возможность сборки по каждой детали. Код: // считываю все товары из базы ВидТовара2 = Справочники.ВидыНоменклатуры.ЮНИТЕ; ЗапросСписок = Новый Запрос; ЗапросСписок.Текст = "ВЫБРАТЬ | Номенклатура.Ссылка |ИЗ | Справочник.Номенклатура КАК Номенклатура |ГДЕ | Номенклатура.ВидНоменклатуры = &ВидТовара | И Номенклатура.ЭтоГруппа = ЛОЖЬ" ; ЗапросСписок.УстановитьПараметр("ВидТовара", ВидТовара2); ВыборкаСписок = ЗапросСписок.Выполнить().Выбрать(); Пока ВыборкаСписок.Следующий() Цикл КоличествоПотенциал = 10000000; //получаю по товару его комплектующие ЗапросТакым = Новый Запрос; ЗапросТакым.Текст = "ВЫБРАТЬ | КомплектующиеНоменклатурыНовый.Номенклатура, | КомплектующиеНоменклатурыНовый.Комплектующая, | КомплектующиеНоменклатурыНовый.Количество |ИЗ | РегистрСведений.КомплектующиеНоменклатурыНовый КАК КомплектующиеНоменклатурыНовый |ГДЕ | КомплектующиеНоменклатурыНовый.Номенклатура = &Такым" ; ЗапросТакым.УстановитьПараметр("Такым", ВыборкаСписок.ссылка); РезультатТакым = ЗапросТакым.Выполнить(); Если НЕ РезультатТакым.Пустой() Тогда ВыборкаТакым = ЗапросТакым.Выполнить().Выбрать(); Пока ВыборкаТакым.Следующий() Цикл; //каждую комплектующую проверяю по динамической таблице остатков и если все ОК, то минусую количество детали в динамической таблице ПараметрыОтбора = Новый Структура; ПараметрыОтбора.Вставить("Юните", ВыборкаТакым.Комплектующая); НайденныеСтроки = Динамика.НайтиСтроки(ПараметрыОтбора); КоличествоНайденныхСтрок = НайденныеСтроки.Количество(); Если КоличествоНайденныхСтрок = 0 Тогда КоличествоПотенциал = 0; КонецЕсли; Для каждого Стр из НайденныеСтроки Цикл Если Цел(Стр.Количество/ВыборкаТакым.Количество) < КоличествоПотенциал Тогда КоличествоПотенциал = Цел(Стр.Количество/ВыборкаТакым.Количество); КонецЕсли; КонецЦикла; Для каждого Стр Из НайденныеСтроки Цикл Стр.Количество = Стр.Количество - КоличествоПотенциал*ВыборкаТакым.Количество; Если Стр.Количество = 0 Тогда Динамика.Удалить(Стр); КонецЕсли; КонецЦикла; КонецЦикла; //если товар собрать можно, то добавляю строчку в таблицу с потенциальными товарами Если КоличествоПотенциал > 0 Тогда НовСтрТак = Такым.Добавить(); НовСтрТак.Такым =ВыборкаСписок.Ссылка; НовСтрТак.Количество = КоличествоПотенциал; КонецЕсли; КонецЕсли; КонецЦикла; Проблема в чем. Считываются данные по первому товару Т1, все ОК, программа понимает, что можно собрать 3 шт. Т1, после этого остатки в динамической таблице выглядят так: Д2 - 1 шт. Д3 - 2 шт. Когда начинается проверка собираемости второго товара Т2, происходит проверку по каждой комплектующей, первая комплектующая Д2 есть в остатке - 1 шт., соответственно динамическая таблица обновляется, но вот Д4 как оказывается нет в остатке и товар собрать нельзя, но как при этом вернуть обновление динамической таблицы, которое уже было выполнено в ходе проверки по первой комплектующей Д2 ? Сорри за размытое объяснение, может просто будут у кого идеи в какую сторону рыть ? |
|||
1
pumbaEO
23.03.12
✎
18:42
|
Может стоит обратить внимание на симплекс метод? Оптимальное решение? Сделать модель?
|
|||
2
Михаил Козлов
23.03.12
✎
20:28
|
(1) Симплекс (алгоритм решения задачи линейного программирования - ЛП) можно применить к этой задаче, если коэфф. вхождения детали в товар = 1. Иначе может получиться дробное количество собранного товара.
Формально это задача целочисленного линейного программирования (не очень хороший термин): Aij - сколько деталей j идет на сборку 1 товара i; Bj - остаток детали j; Xi - сколько собираем товара i. Ограничения: СУММА(Aij*Xi)<=Bj. Xi>=0. Функционал в (0) неопределен. Можно предположить, что это что-то типа суммарной "ценности" собранных товаров: СУММА(Ci*Xi) => MAX. Судя по всему, здесь может хорошо сработать неявное ветвление (схема ветвей и границ с отсечением по результату решения релаксированной задачи ЛП). Или какой-либо вариант "жадного" алгоритма (как в задаче о ранце. Только сразу не понятно, как ранжировать товары: в ранце 1 ограничение и ранжирование по отношению "стоимости" к "весу"). В любом случае имеет смысл повозиться в этом направлении. Если автор пришлет конкретные численные варианты, мог бы попробовать реализовать (мыло в профиле). |
|||
3
Ткачев
23.03.12
✎
20:43
|
А где "- Запрос в цикле, фу как не хорошо..." ?
|
|||
4
МихаилМ
24.03.12
✎
01:07
|
записывайте
промежуточные вычеты в отдельную таблицу если набрать запчастей на деталь не удалось переписывайте обратно. |
|||
5
Rumpil
25.03.12
✎
14:29
|
(4) вот как это обратно все переписывать то ? ) у меня на этом заскок
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |