Имя: Пароль:
1C
1С v8
Некорректно работает обработка
,
0 discant
 
15.06.12
10:08
Добрый день, господа гуру!
Есть такой алгоритм:
Создать внешнюю обработку, которая для выбранного документа «Заказ на пр-во» (либо списка документов) формирует серию подчиненных заказов на пр-во.

При выборе в запросе показывать только те документы, у которых:
1.    Поле «основной заказ» - пустое
2.    На основании которых не введено ни одного документа «заказ на про-во»
Алгоритм работы:
- Обработка должна на основании выбранного основного заказа формировать серию подчиненных заказов (в соответствии с деревом спецификации) по типовому механизму ввода на основании, пока в самом последнем заказе каждой «ветки» на закладке «материалы» не останутся только номенклатурные позиции с видом воспроизводства «закупка».
- Отличие от типового механизма в том, что на каждую подсборку необходимо формировать отдельный заказ.

Заполнение документа:
«подразделение» - Свойство «цех» соответствующего  элемента номенклатуры
«исполнение» - («запуск» - 1) поля заказа-основания
«запуск» - «исполнение» - «срок изготовления», где «срок изготовления» Свойство соответствующего элемента номенклатуры
Остальные поля заполнять, как работает типовой механизм при вводе на основании.
Код обработки приведу в следующем посте. Суть в том, что вне зависимости от материалов, обработка создает только 1 документ, хотя в материалах далеко не одна позиция. В чем ошибка?
1 Нуф-Нуф
 
15.06.12
10:10
ждем следующего поста
2 discant
 
15.06.12
10:12
Процедура КнопкаВыполнитьНажатие(Кнопка)
   Если НЕ ЗначениеЗаполнено(ПроизвЗаказ) Тогда
       Предупреждение("Выберите главный документ <<Заказы на производство>>!");
       Возврат;
   КонецЕсли;
   Если ПроизвЗаказ.Материалы.Количество() = 0 Тогда
       Предупреждение("Заполните табличную часть "+"""Материалы""");
       Возврат;
   КонецЕсли;    
   Для каждого Объект Из РегистрыНакопления Цикл

           Объект.УстановитьИспользованиеИтогов(Истина);

   КонецЦикла;    
   
   
   ДопПараметры = Новый Структура;    
   
   МассивПолуфабрикаты = Новый Массив;
   МассивПолуфабрикаты.Добавить(Перечисления.ВидыВоспроизводстваНоменклатуры.Производство);
   
   ДопПараметры.Вставить("ВидВоспроизводства",      МассивПолуфабрикаты);
   ДопПараметры.Вставить("ИмяРеквЗаказТабЧасть",    "Заказ");
   ДопПараметры.Вставить("ВернутьРезультатЗапроса", Истина);
   
   РезЗапроса = Неопределено;
   ЗаказыНаПроизводствоИПереработку.ЗаполнитьТабличнуюЧастьПоПотребностямЗаказаНаПроизводство(РезЗапроса, ПроизвЗаказ, ДопПараметры);
   
   // Создаем список значений подразделений.
   СписокПодр = Новый СписокЗначений;
   Обход = РезЗапроса.Выбрать();
   Пока Обход.СледующийПоЗначениюПоля("Подразделение") Цикл
       Если СписокПодр.НайтиПоЗначению(Обход.Подразделение) = неопределено Тогда
           СписокПодр.Добавить(Обход.Подразделение);
       КонецЕсли;
   КонецЦикла;
   
   Если СписокПодр.Количество() > 0 Тогда
       Для Каждого тт Из СписокПодр Цикл
           ЗП = Документы.ЗаказНаПроизводство.СоздатьДокумент();    
           ЗаполнениеДокументов.ЗаполнитьШапкуДокументаПоОснованию(ЗП, ПроизвЗаказ);
           ЗП.ОсновнойЗаказНаПроизводство = ПроизвЗаказ;
           ЗП.Подразделение = тт.Значение;
           ЗП.Дата = ТекущаяДата();
           ЗП.ДатаЗапуска = ПроизвЗаказ.ДатаЗапуска;
           ЗП.ДатаИсполнения = ПроизвЗаказ.ДатаИсполнения;
           ЗП.УстановитьНовыйНомер(ПроизвЗаказ.Организация.Префикс);
           ЗП.Ответственный =  глЗначениеПеременной("глТекущийПользователь");
           //вычисляем номер для ДереваЗаказов
           //Вытаскиваем № - Цифры.
           Если НЕ ЗначениеЗаполнено(ЗП.ДеревоЗаказов) Тогда
               цц = "0123456789";
               ном = "";
               длинаНомера = СтрДлина(ЗП.Номер);
               ии = длинаНомера;
               Пока ии > 0 Цикл
                   Если Найти(цц,Сред(ЗП.Номер,ии,1)) > 0 Тогда
                       ном = Сред(ЗП.Номер,ии,1) + ном;
                   Иначе
                       Прервать;
                   КонецЕсли;    
                   ии = ии - 1;
               КонецЦикла;    
               ном = СокрЛП(ПроизвЗаказ.ДеревоЗаказов)+"_"+Строка(Формат(Число(ном),"ЧГ=0"));
               ЗП.ДеревоЗаказов = ном;
           КонецЕсли;
           
           Обход = РезЗапроса.Выбрать();
           Пока Обход.Следующий() Цикл
               Если тт.Значение = Неопределено ИЛИ тт.Значение = Обход.Подразделение Тогда
                   // Заполняем таб. часть Продукция
                   НоваяСтрока = ЗП.Продукция.Добавить();
                   ЗаполнитьЗначенияСвойств(НоваяСтрока, Обход);
                   НоваяСтрока.Количество = Обход.Количество * Обход.КоэффициентХраненияОстатков / Обход.Коэффициент;
                   НоваяСтрока.Спецификация = УправлениеПроизводством.ОпределитьСпецификациюПоУмолчанию(НоваяСтрока.Номенклатура, НоваяСтрока.ХарактеристикаНоменклатуры, ЗП.Дата, ЗП.Подразделение);
               КонецЕсли;
           КонецЦикла;
           //Заполняем Табл. часть Материалы:
           
           
           ТаблицаИсходныеКомплектующие = ЗП.Материалы.Выгрузить();
           
           Параметры = Новый Структура("ПараметрыВыпуска, КоличествоУровнейРазузлования, ДатаСпецификации");
           
           Для Каждого СтрокаТабличнойЧасти Из ЗП.Продукция Цикл
               Если НЕ ЗначениеЗаполнено(СтрокаТабличнойЧасти.Спецификация) Тогда
                   Продолжить;
               КонецЕсли;
               
               РезультатРазузлования = Новый Структура("ИсходныеКомплектующие");
               
               СтруктураИсточник = Новый Структура("Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Количество, Спецификация");
               ЗаполнитьЗначенияСвойств(СтруктураИсточник, СтрокаТабличнойЧасти);
               
               ПараметрыВыпуска = Новый Соответствие;
               Для Каждого ПараметрВыпуска из ЗП.ПараметрыВыпускаПродукции Цикл
                   
                   Если ПараметрВыпуска.КлючСвязи = СтрокаТабличнойЧасти.КлючСвязи Тогда
                       ПараметрыВыпуска.Вставить(ПараметрВыпуска.ВидПараметра.Наименование, ПараметрВыпуска.Значение);
                   КонецЕсли;
                   
               КонецЦикла;
               
               Параметры.ПараметрыВыпуска = ПараметрыВыпуска;
               Параметры.КоличествоУровнейРазузлования = 1;
               Параметры.ДатаСпецификации = ЗП.Дата;
               
               МассивОшибок = РазузлованиеНоменклатуры.РазузловатьНоменклатуру(СтруктураИсточник, РезультатРазузлования, Параметры);
               
               Если МассивОшибок.Количество() > 0 Тогда
                   
                   Для каждого Ошибка из МассивОшибок Цикл
                       
                       ОбщегоНазначения.Сообщение("Ошибка: " + Ошибка.Причина, Ошибка.СтатусОшибки);
                       ОбщегоНазначения.Сообщение(" Спецификация: " + Ошибка.Спецификация);
                       ОбщегоНазначения.Сообщение(" Номер строки: " + Ошибка.НомерСтроки);
                       ОбщегоНазначения.Сообщение(" Описание ошибки: " + Ошибка.ОписаниеОшибки);
                       
                   КонецЦикла;
                   
               КонецЕсли;
               
               Если РезультатРазузлования.ИсходныеКомплектующие = Неопределено Тогда
                   Продолжить;
               КонецЕсли;
               
               ИсходныеКомплектующие = РезультатРазузлования.ИсходныеКомплектующие;
               
               ИсходныеКомплектующие.ЗаполнитьЗначения(тт.Значение, "Подразделение");
               //заполним подразделение по основной спецификации полуфабрикатов
               Для каждого Строка из ИсходныеКомплектующие цикл
                   ПодразделениеНоменклатуры = ЗаказыНаПроизводствоИПереработку.ПолучитьПодразделениеИзСпецификации(Строка.Спецификация,Строка.Номенклатура,Строка.ХарактеристикаНоменклатуры);
                   Если ЗначениеЗаполнено(ПодразделениеНоменклатуры) Тогда
                       Строка.Подразделение = ПодразделениеНоменклатуры;
                   КонецЕсли;
               КонецЦикла;
               
               ИсходныеКомплектующие.Колонки.Добавить("Продукция");
               ИсходныеКомплектующие.Колонки.Добавить("ХарактеристикаПродукции");
               
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.Номенклатура, "Продукция");
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.ХарактеристикаНоменклатуры, "ХарактеристикаПродукции");
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.Спецификация, "Спецификация");
               
               ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ИсходныеКомплектующие, ТаблицаИсходныеКомплектующие);
               
           КонецЦикла;
           
           ТаблицаИсходныеКомплектующие.Свернуть("Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, ВидВоспроизводства, Спецификация, Подразделение, Продукция, ХарактеристикаПродукции", "Количество");
           
           ЗП.Материалы.Загрузить(ТаблицаИсходныеКомплектующие);
           
           Для Каждого СтрокаТабличнойЧасти Из ЗП.Материалы Цикл
               
               ОбработкаТабличныхЧастей.ЗаполнитьЕдиницуМестТабЧасти(СтрокаТабличнойЧасти, ЭтотОбъект, Ложь);        
               
           КонецЦикла;
           ЗП.Записать();
           Сообщить("Документ "+СокрЛП(ЗП));
           // Вызываем процедуру для записанного документа, чтобы на основании него нарисовать след. уровень
           СоздатьВнутреннийУровень(ЗП.Ссылка);
       КонецЦикла;
       Предупреждение("Документы созданы. Пожалуйста проверьте их и проведите!");
   КонецЕсли;
КонецПроцедуры
//*************************************************************************
Процедура СоздатьВнутреннийУровень(ВерхЗаказ)
   ДопПараметры = Новый Структура;    
   
   МассивПолуфабрикаты = Новый Массив;
   МассивПолуфабрикаты.Добавить(Перечисления.ВидыВоспроизводстваНоменклатуры.Производство);
   
   ДопПараметры.Вставить("ВидВоспроизводства",      МассивПолуфабрикаты);
   ДопПараметры.Вставить("ИмяРеквЗаказТабЧасть",    "Заказ");
   ДопПараметры.Вставить("ВернутьРезультатЗапроса", Истина);
   
   РезЗапроса = Неопределено;
   ЗаказыНаПроизводствоИПереработку.ЗаполнитьТабличнуюЧастьПоПотребностямЗаказаНаПроизводство(РезЗапроса, ВерхЗаказ, ДопПараметры);
   
   // Создаем список значений подразделений.
   СписокПодр = Новый СписокЗначений;
   Обход = РезЗапроса.Выбрать();
   Пока Обход.СледующийПоЗначениюПоля("Подразделение") Цикл
       Если СписокПодр.НайтиПоЗначению(Обход.Подразделение) = неопределено Тогда
           СписокПодр.Добавить(Обход.Подразделение);
       КонецЕсли;
   КонецЦикла;
   
   Если СписокПодр.Количество() > 0 Тогда
       Для Каждого тт Из СписокПодр Цикл
           ЗП = Документы.ЗаказНаПроизводство.СоздатьДокумент();    
           ЗаполнениеДокументов.ЗаполнитьШапкуДокументаПоОснованию(ЗП, ВерхЗаказ);
           ЗП.ОсновнойЗаказНаПроизводство = ВерхЗаказ;
           ЗП.Подразделение = тт.Значение;
           ЗП.Дата = Текущаядата();
           ЗП.ДатаЗапуска = ВерхЗаказ.ДатаЗапуска;
           ЗП.ДатаИсполнения = ВерхЗаказ.ДатаИсполнения;
           ЗП.УстановитьНовыйНомер(ВерхЗаказ.Организация.Префикс);
           ЗП.Ответственный =  глЗначениеПеременной("глТекущийПользователь");
           //вычисляем номер для ДереваЗаказов
           //Вытаскиваем № - Цифры.
           Если НЕ ЗначениеЗаполнено(ЗП.ДеревоЗаказов) Тогда
               цц = "0123456789";
               ном = "";
               длинаНомера = СтрДлина(ЗП.Номер);
               ии = длинаНомера;
               Пока ии > 0 Цикл
                   Если Найти(цц,Сред(ЗП.Номер,ии,1)) > 0 Тогда
                       ном = Сред(ЗП.Номер,ии,1) + ном;
                   Иначе
                       Прервать;
                   КонецЕсли;    
                   ии = ии - 1;
               КонецЦикла;    
               ном = СокрЛП(ВерхЗаказ.ДеревоЗаказов)+"_"+Строка(Формат(Число(ном),"ЧГ=0"));
               ЗП.ДеревоЗаказов = ном;
           КонецЕсли;
           
           Обход = РезЗапроса.Выбрать();
           Пока Обход.Следующий() Цикл
               Если тт.Значение = Неопределено ИЛИ тт.Значение = Обход.Подразделение Тогда
                   // Заполняем таб. часть Продукция
                   НоваяСтрока = ЗП.Продукция.Добавить();
                   ЗаполнитьЗначенияСвойств(НоваяСтрока, Обход);
                   НоваяСтрока.Количество = Обход.Количество * Обход.КоэффициентХраненияОстатков / Обход.Коэффициент;
                   НоваяСтрока.Спецификация = УправлениеПроизводством.ОпределитьСпецификациюПоУмолчанию(НоваяСтрока.Номенклатура, НоваяСтрока.ХарактеристикаНоменклатуры, ЗП.Дата, ЗП.Подразделение);
               КонецЕсли;
           КонецЦикла;
           //Заполняем Табл. часть Материалы:
           
           
           ТаблицаИсходныеКомплектующие = ЗП.Материалы.Выгрузить();
           
           Параметры = Новый Структура("ПараметрыВыпуска, КоличествоУровнейРазузлования, ДатаСпецификации");
           
           Для Каждого СтрокаТабличнойЧасти Из ЗП.Продукция Цикл
               Если НЕ ЗначениеЗаполнено(СтрокаТабличнойЧасти.Спецификация) Тогда
                   Продолжить;
               КонецЕсли;
               
               РезультатРазузлования = Новый Структура("ИсходныеКомплектующие");
               
               СтруктураИсточник = Новый Структура("Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, Количество, Спецификация");
               ЗаполнитьЗначенияСвойств(СтруктураИсточник, СтрокаТабличнойЧасти);
               
               ПараметрыВыпуска = Новый Соответствие;
               Для Каждого ПараметрВыпуска из ЗП.ПараметрыВыпускаПродукции Цикл
                   
                   Если ПараметрВыпуска.КлючСвязи = СтрокаТабличнойЧасти.КлючСвязи Тогда
                       ПараметрыВыпуска.Вставить(ПараметрВыпуска.ВидПараметра.Наименование, ПараметрВыпуска.Значение);
                   КонецЕсли;
                   
               КонецЦикла;
               
               Параметры.ПараметрыВыпуска = ПараметрыВыпуска;
               Параметры.КоличествоУровнейРазузлования = 1;
               Параметры.ДатаСпецификации = ЗП.Дата;
               
               МассивОшибок = РазузлованиеНоменклатуры.РазузловатьНоменклатуру(СтруктураИсточник, РезультатРазузлования, Параметры);
               
               Если МассивОшибок.Количество() > 0 Тогда
                   
                   Для каждого Ошибка из МассивОшибок Цикл
                       
                       ОбщегоНазначения.Сообщение("Ошибка: " + Ошибка.Причина, Ошибка.СтатусОшибки);
                       ОбщегоНазначения.Сообщение(" Спецификация: " + Ошибка.Спецификация);
                       ОбщегоНазначения.Сообщение(" Номер строки: " + Ошибка.НомерСтроки);
                       ОбщегоНазначения.Сообщение(" Описание ошибки: " + Ошибка.ОписаниеОшибки);
                       
                   КонецЦикла;
                   
               КонецЕсли;
               
               Если РезультатРазузлования.ИсходныеКомплектующие = Неопределено Тогда
                   Продолжить;
               КонецЕсли;
               
               ИсходныеКомплектующие = РезультатРазузлования.ИсходныеКомплектующие;
               
               ИсходныеКомплектующие.ЗаполнитьЗначения(тт.Значение, "Подразделение");
               //заполним подразделение по основной спецификации полуфабрикатов
               Для каждого Строка из ИсходныеКомплектующие цикл
                   ПодразделениеНоменклатуры = ЗаказыНаПроизводствоИПереработку.ПолучитьПодразделениеИзСпецификации(Строка.Спецификация,Строка.Номенклатура,Строка.ХарактеристикаНоменклатуры);
                   Если ЗначениеЗаполнено(ПодразделениеНоменклатуры) Тогда
                       Строка.Подразделение = ПодразделениеНоменклатуры;
                   КонецЕсли;
               КонецЦикла;
               
               ИсходныеКомплектующие.Колонки.Добавить("Продукция");
               ИсходныеКомплектующие.Колонки.Добавить("ХарактеристикаПродукции");
               
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.Номенклатура, "Продукция");
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.ХарактеристикаНоменклатуры, "ХарактеристикаПродукции");
               ИсходныеКомплектующие.ЗаполнитьЗначения(СтрокаТабличнойЧасти.Спецификация, "Спецификация");
               
               ОбщегоНазначения.ЗагрузитьВТаблицуЗначений(ИсходныеКомплектующие, ТаблицаИсходныеКомплектующие);
               
           КонецЦикла;
           
           ТаблицаИсходныеКомплектующие.Свернуть("Номенклатура, ХарактеристикаНоменклатуры, ЕдиницаИзмерения, Коэффициент, ВидВоспроизводства, Спецификация, Подразделение, Продукция, ХарактеристикаПродукции", "Количество");
           
           ЗП.Материалы.Загрузить(ТаблицаИсходныеКомплектующие);
           
           Для Каждого СтрокаТабличнойЧасти Из ЗП.Материалы Цикл
               
               ОбработкаТабличныхЧастей.ЗаполнитьЕдиницуМестТабЧасти(СтрокаТабличнойЧасти, ЭтотОбъект, Ложь);        
               
           КонецЦикла;
           ЗП.Записать();
           Сообщить("Документ "+СокрЛП(ЗП));
           // Вызываем процедуру для записанного документа
           СоздатьВнутреннийУровень(ЗП.Ссылка);
       КонецЦикла;
   Иначе
       Возврат;
   КонецЕсли;
   
КонецПроцедуры    

Процедура ПриИзменении(Элемент)
   //Вытаскиваем номер док-та в цифровом виде
   цц = "0123456789";
   ном = "";
   длинаНомера = СтрДлина(ПроизвЗаказ.Номер);
   ии = длинаНомера;
   Пока ии > 0 Цикл
       Если Найти(цц,Сред(ПроизвЗаказ.Номер,ии,1)) > 0 Тогда
           ном = Сред(ПроизвЗаказ.Номер,ии,1) + ном;
       Иначе
           Прервать;
       КонецЕсли;    
       ии = ии - 1;
   КонецЦикла;    
   ном = Строка(Формат(Число(ном),"ЧГ=0"))+"_";
   Длном = СтрДлина(ном);
   // Проверяем, есть ли уже подчиненные док-ты.
   Запрос = Новый Запрос;
   Запрос.Текст =
   "ВЫБРАТЬ
   |    ЗаказНаПроизводство.ОсновнойЗаказНаПроизводство
   |ИЗ
   |    Документ.ЗаказНаПроизводство КАК ЗаказНаПроизводство
   |ГДЕ
   |    (ЗаказНаПроизводство.ОсновнойЗаказНаПроизводство = &ОсновнойЗаказНаПроизводство
   |  ИЛИ ПОДСТРОКА(ЗаказНаПроизводство.Комментарий,1,&Длном) = &ном)
   |    И ЗаказНаПроизводство.Проведен = ИСТИНА";
   
   Запрос.УстановитьПараметр("ОсновнойЗаказНаПроизводство",ПроизвЗаказ.Ссылка);
   Запрос.УстановитьПараметр("Длном",Длном);
   Запрос.УстановитьПараметр("ном",ном);
   
   Выб = Запрос.Выполнить().Выбрать();
   Если Выб.Количество() > 0 Тогда
       Предупреждение("Для документа "+ СокрЛП(ПроизвЗаказ.Ссылка)+" уже выписаны документы Заказа!"+Символы.ПС+"Чтобы заново их создать, необходимо предварительно их удалить(пометить на удаление)!"+Символы.ПС+"Или выбрать верный документ!");
       Возврат;
   КонецЕсли;    
КонецПроцедуры
3 Нуф-Нуф
 
15.06.12
10:14
ужаснах. бросай эту вакансию
4 Mort
 
15.06.12
10:17
Без пузыря не разберешься. Или даже без двух.
5 Alex S D
 
15.06.12
10:18
за 2т. резберусь
6 Mort
 
15.06.12
10:20
Да вообще тут всё просто отладчиком найти. Но размер процедур внушаит ))
7 Maxus43
 
15.06.12
10:21
подозреваю что раза в 2-3 можно сократить код
8 discant
 
15.06.12
10:22
А приведет ли подобное сокращение к желаемому результату?
9 Mort
 
15.06.12
10:25
(8) Неа. Но если бы ты сократил код, сразу бы увидел, что документы создаются по одному на каждое подразделение.
10 discant
 
15.06.12
10:29
На практике создается 1 документ. тя которого заполняется из основного заказа.
11 Нуф-Нуф
 
15.06.12
10:30
отладчик спасет
12 Нуф-Нуф
 
15.06.12
10:30
(10) кстати в какую контору устраиваешься?
13 discant
 
15.06.12
10:30
Я имел ввиду тч продукция из основного заказа
14 Maxus43
 
15.06.12
10:30
одна фраза - "формировать серию подчиненных заказов (в соответствии с деревом спецификации)" - даст сокращение туевой кучи кода посредством НовыйДок.Заполнить(ДокОснование)
а потом лишние строки удалить из НовыйДок и записать... и т.д.
15 discant
 
15.06.12
10:35
А можн конкретнее?
16 Maxus43
 
15.06.12
10:37
(14) + по типовому механизму ввода на основании
точней по этой фразе.
(15) что конкретней? если стандартно на основании заполняеш - не устраивает только то что один док со всеми позициями?
17 discant
 
15.06.12
10:42
Так мне надо получить основной заказ и заказы на каждую подсборку из тч материалы...
18 Maxus43
 
15.06.12
10:48
я в коде не разбирался, по мне дак легче удалить лишние строки после
НовыйДок.Заполнить(ДокОснование);
чем городить такое заполнение.
Заполнили док, оставили там тока первую "подсборку" (что бы это ни было), записали.
Опять заполнили - удалили всё кроме второй "подсборки" и т.д.

З.ы. это я по вопросу чтоб сократить код, что у тебя не работает помойму никто не понял