Как проверить и поправить код с дубликатами процедур в 1С?

База знаний Одина — Одинэсника Форумы ODIN — Форум по 1С Предприятию Как проверить и поправить код с дубликатами процедур в 1С?

Просмотр 1 ветки ответов
  • Автор
    Сообщения
    • #37142
      Фото аватараOdineski
      Участник

        можешь проверить код &НаКлиенте
        Процедура ЗаполнитьИзНДС(Команда)
        ГодОтчета = ЭтотОбъект[«ОТЧ»].ПривестиЗначение(_ОтчетГод);
        Если ГодОтчета < 2010 Или ГодОтчета > 2099 Тогда
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Некорректно указан год», , «_ОтчетГод»);
        Возврат;
        КонецЕсли;
        Если Не ЗначениеЗаполнено(_Период) Тогда
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Не указан период», , «_Период»);
        Возврат;
        КонецЕсли;

        ЗаполнитьИзДокументаНаСервере(ГодОтчета, _Период);
        КонецПроцедуры

        &НаСервере
        Процедура ЗаполнитьИзДокументаНаСервере(ГодОтчета, Период)
        // Очистка табличной части. Уточните имя таблицы (например, «Реестр», «СписокДокументов»)
        ТабЧасть = ЭтотОбъект.ТабличнаяЧасть; // ИЛИ ЭтотОбъект.Реестр, ЭтотОбъект.Список и т.д.
        ТабЧасть.Очистить();

        Запрос = Новый Запрос;
        Запрос.Текст =
        «ВЫБРАТЬ
        | ПодтверждениеНДС.Ссылка КАК Документ,
        | ПодтверждениеНДС.Дата КАК Дата,
        | ПодтверждениеНДС.Ответственный КАК Ответственный,
        | ПодтверждениеНДС.Сумма КАК Сумма
        |ИЗ
        | Документ.ПодтверждениеНулевойСтавкиНДС КАК ПодтверждениеНДС
        |ГДЕ
        | ПодтверждениеНДС.Дата МЕЖДУ &ДатаНач И &ДатаКонец
        |УПОРЯДОЧИТЬ ПО
        | ПодтверждениеНДС.Дата УБЫВ»;

        Запрос.УстановитьПараметр(«ДатаНач», НачалоДня(Период));
        Запрос.УстановитьПараметр(«ДатаКонец», КонецДня(Период));

        Результат = Запрос.Выполнить();
        Выборка = Результат.Выбрать();

        Пока Выборка.Следующий() Цикл
        НоваяСтрока = ТабЧасть.Добавить();
        НоваяСтрока.Документ = Выборка.Документ;
        НоваяСтрока.Дата = Выборка.Дата;
        НоваяСтрока.Ответственный = Выборка.Ответственный;
        НоваяСтрока.Сумма = Выборка.Сумма;
        КонецЦикла;
        КонецПроцедуры

        &НаКлиенте
        Процедура ФормаЗаполненияДействие(Команда)
        ГодОтчета = ЭтотОбъект[«ОТЧ»].ПривестиЗначение(_ОтчетГод);
        Если ГодОтчета < 2010 Или ГодОтчета > 2099 Тогда
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Некорректно указан год», , «_ОтчетГод»);
        Возврат;
        КонецЕсли;
        Если Не ЗначениеЗаполнено(_Период) Тогда
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Не указан период», , «_Период»);
        Возврат;
        КонецЕсли;

        ЗаполнитьИзДокументаНаСервере(ГодОтчета, _Период);
        КонецПроцедуры

        &НаСервере
        Процедура ЗаполнитьИзДокументаНаСервере(ГодОтчета, Период)
        // Очищаем старые данные
        _РеестрДокПОбНЛ.Очистить();
        _ПредТипДог.Строки.Очистить();

        // Запрос к документу. Имена реквизитов уточните по вашей конфигурации!
        Запрос = Новый Запрос;
        Запрос.Текст =
        «ВЫБРАТЬ
        | ПНДС.Ссылка,
        | ПНДС.КодОперации,
        | ПНДС.ВидОперации,
        | ПНДС.Сумма,
        | ПНДС.Контрагент,
        | Контрагент.Наименование КАК НаименованиеКонтрагента,
        | Контрагент.ИНН КАК ИНН,
        | Контрагент.КПП КАК КПП,
        | ПНДС.ДокументОснование,
        | ДокОснование.Номер КАК НомерДокумента,
        | ДокОснование.Дата КАК ДатаДокумента,
        | ВЫРАЗИТЬ(ДокОснование.Ссылка КАК СТРОКА(150)) КАК ТипДокумента
        |ИЗ
        | Документ.ПодтверждениеНулевойСтавкиНДС КАК ПНДС
        | ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагент ПО ПНДС.Контрагент = Контрагент.Ссылка
        | ЛЕВОЕ СОЕДИНЕНИЕ Документ.УниверсальныйПередаточныйДокумент КАК ДокОснование ПО ПНДС.ДокументОснование = ДокОснование.Ссылка
        |ГДЕ
        | ПНДС.Дата МЕЖДУ &ДатаНач И &ДатаКонец
        |УПОРЯДОЧИТЬ ПО
        | ПНДС.КодОперации, ПНДС.ВидОперации, НаименованиеКонтрагента, ПНДС.Дата»;

        Запрос.УстановитьПараметр(«ДатаНач», НачалоДня(Период));
        Запрос.УстановитьПараметр(«ДатаКонец», КонецДня(Период));

        Результат = Запрос.Выполнить();
        Выборка = Результат.Выбрать();

        Если Не Выборка.Следующий() Тогда
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Нет документов ПодтверждениеНулевойСтавкиНДС за указанный период.»);
        Возврат;
        КонецЕсли;

        // Словари для группировки
        СоответствиеКодВид = Новый Соответствие; // ключ = Код|Вид -> строка _РеестрДокПОбНЛ
        УИД_КодВид = Новый Соответствие; // ключ -> УИД строки реестра

        // Первый проход: создаём строки в реестре по уникальным комбинациям код+вид
        Выборка.Сбросить();
        Пока Выборка.Следующий() Цикл
        Ключ = Выборка.КодОперации + «|» + Выборка.ВидОперации;
        Если Не СоответствиеКодВид.Свойство(Ключ) Тогда
        НоваяСтрока = _РеестрДокПОбНЛ.Добавить();
        НоваяСтрока.УИД = Новый УникальныйИдентификатор;
        НоваяСтрока.КодОпер = Выборка.КодОперации;
        НоваяСтрока.ВидОпер = Выборка.ВидОперации;
        НоваяСтрока.СумНеоблОпер = 0;
        НоваяСтрока.ОписаниеОперации = «Операции по коду » + Выборка.КодОперации;
        СоответствиеКодВид.Вставить(Ключ, НоваяСтрока);
        УИД_КодВид.Вставить(Ключ, НоваяСтрока.УИД);
        КонецЕсли;
        КонецЦикла;

        // Для каждого уникального код+вид создаём корневой узел в дереве
        Для каждого Ключ Из УИД_КодВид Цикл
        Корневой = _ПредТипДог.Строки.Добавить();
        Корневой.УИД = Ключ.Значение;
        Корневой.УИДЛок = Новый УникальныйИдентификатор;
        Корневой.ИмяФайлДог = «»;
        Корневой.ОписаниеКА = «Документы по коду операции»;
        Корневой.СумОпер = 0;
        КонецЦикла;

        // Второй проход: добавляем контрагентов и документы
        Выборка.Сбросить();
        СоответствиеКонтрагентов = Новый Соответствие; // ключ = УИД_КодВид|ИНН|КПП|Наименование

        Пока Выборка.Следующий() Цикл
        КлючКодВид = Выборка.КодОперации + «|» + Выборка.ВидОперации;
        УИД_Родителя = УИД_КодВид[КлючКодВид];
        Корневой = _ПредТипДог.Строки.Найти(УИД_Родителя, «УИД»);
        Если Корневой = Неопределено Тогда Продолжить; КонецЕсли;

        // Ключ контрагента
        ИНН = СокрЛП(Выборка.ИНН);
        КПП = СокрЛП(Выборка.КПП);
        Наименование = СокрЛП(Выборка.НаименованиеКонтрагента);
        КлючКонтрагента = Строка(УИД_Родителя) + «|» + ИНН + «|» + КПП + «|» + Наименование;

        УзелКонтрагента = Неопределено;
        Если Не СоответствиеКонтрагентов.Свойство(КлючКонтрагента, УзелКонтрагента) Тогда
        УзелКонтрагента = Корневой.Строки.Добавить();
        ЗаполнитьЗначенияСвойств(УзелКонтрагента, Новый Структура(«УИД,НаимОрг,ИННЮЛ,КПП,СумОпер,УИДЛок,ОписаниеКА»));
        УзелКонтрагента.УИД = УИД_Родителя;
        УзелКонтрагента.УИДЛок = Новый УникальныйИдентификатор;
        УзелКонтрагента.НаимОрг = Наименование;
        УзелКонтрагента.ИННЮЛ = ИНН;
        УзелКонтрагента.КПП = КПП;
        УзелКонтрагента.СумОпер = 0;
        УзелКонтрагента.ОписаниеКА = Наименование + «, ИНН/КПП: » + ИНН + «/» + КПП;
        СоответствиеКонтрагентов.Вставить(КлючКонтрагента, УзелКонтрагента);
        КонецЕсли;

        // Добавляем документ, если ещё нет
        Номер = СокрЛП(Выборка.НомерДокумента);
        ДатаДок = Выборка.ДатаДокумента;
        ТипДок = «УТД»;
        Есть = Ложь;
        Для Каждого СтрДок Из УзелКонтрагента.Строки Цикл
        Если СтрДок.НомДок = Номер И СтрДок.ДатаДок = ДатаДок Тогда Есть = Истина; Прервать; КонецЕсли;
        КонецЦикла;
        Если Не Есть Тогда
        УзелДокумента = УзелКонтрагента.Строки.Добавить();
        УзелДокумента.УИД = УИД_Родителя;
        УзелДокумента.УИДЛок = Новый УникальныйИдентификатор;
        УзелДокумента.ТипДок = ТипДок;
        УзелДокумента.НомДок = Номер;
        УзелДокумента.ДатаДок = ДатаДок;
        УзелДокумента.ОписаниеКА = ТипДок + » №» + Номер + » от » + Формат(ДатаДок, «ДЛФ=DD; ДП=-«);
        УзелДокумента.Сумма = Выборка.Сумма;
        // Сумма документа будет видна в колонке «Сумма» (если она есть в табличной части)
        КонецЕсли;

        // Накопление сумм
        УзелКонтрагента.СумОпер = УзелКонтрагента.СумОпер + Выборка.Сумма;
        Корневой.СумОпер = Корневой.СумОпер + Выборка.Сумма;

        СтрокаРеестра = СоответствиеКодВид[КлючКодВид];
        СтрокаРеестра.СумНеоблОпер = СтрокаРеестра.СумНеоблОпер + Выборка.Сумма;
        КонецЦикла;

        Модифицированность = Истина;
        Доступность = Истина;
        ОбщегоНазначенияКлиент.СообщитьПользователю(«Загрузка завершена. Обработано документов: » + _РеестрДокПОбНЛ.Количество());
        КонецПроцедуры

      • #37143
        bot_avaOdin — Одинэсник
        Участник

          Код в целом выглядит логично, но есть несколько моментов, на которые стоит обратить внимание и поправить:

          1. Дублирование процедуры с одинаковым именем ЗаполнитьИзДокументаНаСервере
          В коде две процедуры с одинаковым именем, но разным содержанием. В 1С это не допускается — будет ошибка компиляции. Нужно переименовать одну из процедур, например, в ЗаполнитьИзДокументаНаСервере_Простой и ЗаполнитьИзДокументаНаСервере_Расширенный или объединить логику.

          2. Обращение к табличной части ЭтотОбъект.ТабличнаяЧасть
          В первой серверной процедуре есть строка:

          Это невалидно, так как у объекта документа или справочника нет свойства с именем ТабличнаяЧасть. Нужно указать конкретное имя табличной части, например:

          Иначе будет ошибка.

          3. Вызов клиентской процедуры из серверной
          В серверной процедуре вызывается:

          Это клиентская процедура, её нельзя вызвать с сервера напрямую. Нужно либо возвращать результат на клиент и там показывать сообщение, либо использовать механизм событий.

          4. Параметры _ОтчетГод и _Период
          В клиентских процедурах используются переменные _ОтчетГод и _Период. Убедитесь, что они определены и доступны в контексте формы.

          5. Обращение к _РеестрДокПОбНЛ и _ПредТипДог
          В расширенной серверной процедуре используются объекты _РеестрДокПОбНЛ и _ПредТипДог. Убедитесь, что это табличные части или объекты, доступные в контексте ЭтотОбъект. Если это реквизиты формы, то нужно передавать их в процедуру или работать с ними на клиенте.

          6. Использование ОбщегоНазначенияКлиент.СообщитьПользователю
          В клиентских процедурах вызов корректен, но в серверных — нет. Для серверных процедур лучше возвращать результат или использовать ВызватьИсключение для ошибок.

          7. Обработка пустой выборки
          В расширенной серверной процедуре есть проверка:

          Здесь Выборка.Следующий() сдвигает курсор, и при повторном переборе выборки данные будут пропущены. Лучше сделать так:

          Или сохранить результат в переменную.

          8. Вызов Модифицированность = Истина; Доступность = Истина;
          Эти переменные не объявлены и не используются явно. Если это свойства формы, то нужно обращаться через ЭтотОбъект или ЭлементыФормы.

          Рекомендации по исправлению:

          — Переименуйте серверные процедуры с одинаковым именем.
          — Уточните имена табличных частей.
          — В серверных процедурах не вызывайте клиентские методы напрямую.
          — Проверьте доступность переменных и объектов.
          — Исправьте проверку пустой выборки.
          — Если нужно показать сообщение с сервера, возвращайте результат на клиент и там вызывайте СообщитьПользователю.

          Если нужно, могу помочь с конкретным исправленным вариантом кода.

      Просмотр 1 ветки ответов
      • Для ответа в этой теме необходимо авторизоваться.
      База знаний 1С