Список работ

Пример употребления внешнего соединения в 1С:Предприятие 8

Содержание

ВВЕДЕНИЕ

Внешнее соединение 1С позволяет в конфигурации приемника получить доступ к данным базы источника.
Внешнее соединение устанавливается в конфигурации приемника методом Connect следующего COM-объекта:

glCntr = новый COMObject("V82.COMConnector");

Метод Connect принимает строку с параметрами внешнего соединения, например, следующую:

прмСдн = "File = D:\1C8\Sn; Usr = СН; Pwd = 123";

Первая подстрока (до первой точки с запятой) - это путь к информационной базе источника, вторая - это имя зарегистрированного пользователя, третья - пароль пользователя СН.
При отсутствии пароля задаются два первых параметра:

прмСдн = "file = D:\1C8\Sn; usr = СН";

Метод Connect возвращает COM-объект, обеспечивающий соединение приемника с источником.

вс = glCntr.Connect(прмСдн);

Используя этот объект, приемник может получать данные из базы источника, оперируя подходящими встроенными или пользовательскими методами 1С, например:

// Используем встроенный метода 1С НайтиПоКоду
снС = вс.справочники.СерийныеНомера.НайтиПоКоду("sn500");

или

// Используем созданную пользователем функцию
сЗ = вс.вСН.получитьСЗ("sn500");

Функция ПолучитьСЗ определена в общем модуле вСН конфигурации источника, в свойствах которого установлен флажок Внешнее соединение (рис. 1).

Свойство Внешнее соединение общего модуля 1С:Предприятие 8

Рис. 1. Свойства модуля вСН конфигурации-источника

// Возвращает список значений с данными справочника Серийные номера, отвечающий заданному отбору
функция получитьСЗ(сн) экспорт
 тбр = новый структура("Отбор, СтрокаПоиска, ВыборГруппИЭлементов",
  "Код", сн, использованиеГруппИЭлементов.Элементы);
 сЗ = справочники.СерийныеНомера.ПолучитьДанныеВыбора(тбр);
 возврат сЗ;
конецФункции

Есть несколько причин использования внешнего соединения. Одна из них - это наличие в организации хранилища данных, которые используются несколькими конфигурациями. Так, в организации, продающей компьютеры и их комплектующие, а также обеспечивающей из гарантийное обслуживание, возникает хранилище серийных номеров (СН) изделий. Хранилище пополняется данными (серийными номерами и связанной информацией) в момент реализации изделий. В операциях поступления и перемещения изделий серийные номера не фиксируются.
При гарантийном обслуживании, напротив, все операции выполняются в разрезе серийных номеров. Так, при приеме изделий на гарантийное обслуживание серийный номер ищется в хранилище СН и в случае неудачи клиенту отказывают в обслуживание (изделие "чужое", приобретенное в иной организации). Также по СН определяется, не истек ли срок гарантии и является ли контрагент покупателем изделия.
Далее приводятся краткое описание конфигурации гарантийного отдела и хранилища СН. Процесс извлечения данных из хранилища СН и их последующей обработки данных в конфигурации гарантийного отдела рассматривается на примере документа Прием изделий на гарантийное обслуживание. Представлены упрощенные варианты объектов конфигурации.

ОПЕРАЦИИ ГАРАНТИЙНОГО ОТДЕЛА

Организация торгует оптом, поэтому клиент-оптовик приносит для ремонта партию неисправных изделий, которые он, в свою очередь, получил от розничных покупателей.
В гарантийном отделом выполняются следующие операции:

  1. Прием изделий на склад Приема или отказ в приеме.
  2. Начальная диагностика изделия и классификация дефектов.
  3. Подбор и передача изделий одному из подрядчиков для последующего ремонта.
  4. Прием изделий от подрядчика на склад Возврата.
  5. Возврат изделий клиенту. Также изделие может быть заменено иным или компенсировано суммой, равной остаточной стоимости изделия, уменьшаемой по мере его старения.

Кроме того, клиент-оптовик перед доставкой неисправных изделий может прислать их список с тем, чтобы исключить изделия, не подлежащие гарантийному обслуживанию, например чужие и старые. В этом случае организация формирует так называемый ответ RMA с указанием статуса изделия.

Замечание. RMA (Return Merchandise Authorization) - возврат некачественных или неисправных изделий производителю для ремонта, замены или компенсации.
Также организация может перед отправкой изделий подрядчику сформировать запрос RMA по списку отправляемых изделий с тем, чтобы узнать, какие изделия подрядчик готов принять для ремонта, а какие - нет.
Помимо этого, время от времени возникает необходимость оприходования, перемещения или списания изделий.
Во всех перечисленных операциях присутствует СН, что позволяет проследить историю изделия в по его серийному номеру и, главное, вернуть клиенту (если не было замены или компенсации) сданное им изделие.

ХРАНИЛИЩЕ СН

КОНФИГУРАЦИЯ ХРАНИЛИЩА СН

Состав конфигурации-источника, хранилища СН, показан на рис. 2.

Конфигурация СН в 1С:Предприятие 8

Рис. 2. Конфигурация хранилища СН

ЗАПОЛНЕНИЕ ХРАНИЛИЩА СН

ОБРАБОТКИ ЗАГРУЗКИ ДАННЫХ

Хранилище СН пополняется данными из текстовых файлов. Чтение файлов и ввод данных обеспечивают обработки загрузки:
ЗагрузкаК – заполняет справочники Контрагенты, КонтактныеЛица и КонтактныеЛицаКонтрагентов, а также регистр сведений КонтактнаяИнформация.
ЗагрузкаТ – заполняет справочники Номенклатура, Контрагенты (группу Производители) и СерийныеНомера (добавляется серийный номер, код которого равен артикулу изделия).
ЗагрузкаСН – заполняет справочник СерийныеНомера, выполняется после загрузки контрагентов и номенклатуры.
Обработки имеют схожие формы (рис. 3).

Загрузка справочника Контрагенты в 1С:Предприятие 8

Рис. 3. Форма обработки ЗагрузкаК

Весь код располагается в модуле формы обработки.
Поле ввода формы имеет имя Файл и использует в качестве данных одноименный строковый реквизит обработки.
Значение реквизита Файл определяется в процедуре ВыбратьФайл – обработчике события НачалоВыбора поля ввода Файл.

// Определяет значение реквизита Файл
процедура выбратьФайл(элемент, стандартнаяОбработка)
 нДиалог = новый диалогВыбораФайла(режимДиалогаВыбораФайла.Открытие);
 нДиалог.Фильтр = "Текстовый документ (*.txt)|*.txt";
 нДиалог.Заголовок = "Выбор файла с контрагентами";
 если нДиалог.Выбрать() тогда файл = нДиалог.ПолноеИмяФайла конецЕсли;
конецПроцедуры

Просмотр выбранного файла обеспечивает процедура файлОткрытие – обработчик события Открытие поля ввода Файл.

// Просмотр выбранного файла
процедура файлОткрытие(элемент, стандартнаяОбработка)
 если не пустаяСтрока(файл) тогда запуститьПриложение(файл) конецЕсли;
конецПроцедуры

ЗАГРУЗКА ДАННЫХ КОНТРАГЕНТОВ

Строка входного файла содержит следующие данные контрагентов:

Данные разделяются двойной тильдой (рис. 4).

Исходные данные загрузки справочника Контрагенты

Рис. 4. Три строки файла с данными контрагентов

Данные загружаются в группу Клиенты (рис. 5).

Элемент группы Клиенты справочника Контрагенты 1С:Предприятие 8

Рис. 5. Группа клиенты

Данные не редактируются (обновляются при загрузке), но могут быть просмотрены в соответствующих формах (рис. 6 и 7).

Редактирование элемента справочника Контрагенты 1С:Предприятие 8

Рис. 6. Форма элемента справочника Контрагенты

Редактирование записи справочника регистра сведений Контактная информация 1С:Предприятие 8

Рис. 7. Форма списка регистра сведений КонтактнаяИнформация

Выбор входного файла и заполнение справочников Контрагенты, КонтактныеЛица и КонтактныеЛицаКонтрагентов и регистра сведений КонтактнаяИнформация обеспечивает следующий код:

перем спрКЛ, спрКЛК, ткДт;

// Возвращает один элемент текущей строки входного файла,
// то есть подстроку, расположенную либо до первого разделителя,
// либо между разделителями, либо вслед за последним разделителем
// В качестве разделителя употребляется двойная тильда (~~)
функция днЛмнт(тС, п)
 лмнт = сокрЛП(лев(тС, п - 1));
 тС = сред(тС, п + 2);
 п = найти(тС, "~~");
 возврат лмнт;
конецФункции

// Извлекает из текущей строки входного файла код контрагента (кд),
// его наименование (нм), юридический адрес (юА), почтовый адрес (пА),
// телефоны (тл), email (мл) и контактное лицо (кЛц)
функция плчтСтрк(к, тС, кд, нм, юА, пА, тл, мл, кЛц)
 п = найти(тС, "~~");
 если п > 0 тогда
  кд = днЛмнт(тС, п);
  если п > 0 тогда
   нм = днЛмнт(тС, п);
   если п > 0 тогда
    юА = днЛмнт(тС, п);
    если п > 0 тогда
     пА = днЛмнт(тС, п);
     если п > 0 тогда
      тл = днЛмнт(тС, п);
      если п > 0 тогда
       мл = днЛмнт(тС, п);
       кЛц = сокрЛП(тС);
       п = 1;
      конецЕсли;
     конецЕсли;
    конецЕсли;
   конецЕсли;
  конецЕсли;
 конецЕсли;
 если п = 0 тогда предупреждение("Строка " + к + ". Неверный формат данных") конецЕсли;
 возврат п > 0;
конецФункции

// Формирует группу справочник Контрагенты
функция зпГр(спр, нмГр, кдГр)
 спрСГ = спр.НайтиПоКоду("G" + кдГр);
 если спрСГ.Пустая() тогда
  спрБ = спр.СоздатьГруппу();
  спрБ.Код = "G" + кдГр;
  спрБ.Наименование = нмГр;
  спрБ.Записать();
  спрСГ = спрБ.Ссылка;
  сообщить("Добавлена группа " + спрСГ.Наименование);
 конецЕсли;
 возврат спрСГ;
конецФункции

// Формирует запись справочника КонтактныеЛица и запись справочника КонтактныеЛицаКонтрагентов
функция дбвКЛ(спрСЛ, кЛц)
 спрКЛС = спрКЛ.НайтиПоНаименованию(кЛц, истина);
 если спрКЛС.Пустая() тогда
  спрКЛБ = спрКЛ.СоздатьЭлемент();
  спрКЛБ.Записать();
  спрКЛС = спрКЛБ.Ссылка;
 иначе
  спрКЛБ = спрКЛС.ПолучитьОбъект();
 конецЕсли;
 спрКЛБ.Наименование = кЛц;
 спрКЛБ.Описание = "Загрузка " + ткДт;
 спрКЛБ.Записать();
 спрКЛКС = спрКЛК.НайтиПоРеквизиту("КонтактноеЛицо", спрКЛС, , спрСЛ);
 если спрКЛКС.Пустая() тогда
  спрКЛКБ = спрКЛК.СоздатьЭлемент();
  спрКЛКБ.Владелец = спрСЛ;
  спрКЛКБ.КонтактноеЛицо = спрКЛС;
  спрКЛКБ.Записать();
  спрКЛКС = спрКЛКБ.Ссылка;
 иначе
  спрКЛКБ = спрКЛКС.ПолучитьОБъект();
 конецЕсли;
 спрКЛКБ.Наименование = кЛц;
 спрКЛКБ.Комментарий = "Загрузка " + ткДт;;
 спрКЛКБ.Записать();
 возврат спрКЛКС;
конецФункции

// Модифицирует регистр сведений КонтактнаяИнформация
процедура дбвтКНфрмц(спрСЛ, тпКИ, вдКИ, прдст, кммнт)
 мнЗп = регистрыСведений.КонтактнаяИнформация.СоздатьМенеджерЗаписи();
 мнЗп.Объект = спрСЛ;
 мнЗп.Тип = тпКИ;
 мнЗп.Вид = вдКИ;
 мнЗп.Представление = прдст;
 мнЗп.Комментарий = кммнт;
 мнЗп.Период = '20120101';
 мнЗп.Записать();
конецПроцедуры

/ Добавляет или изменяет сведения о контрагенте
функция зпЛ(спр, спрСГ, кд, нм, юА, пА, тл, мл, кЛц)
 спрСЛ = спр.НайтиПоКоду(кд);
 если спрСЛ.Пустая() тогда
  спрБ = спр.СоздатьЭлемент();
  спрБ.Родитель = спрСГ;
  спрБ.Код = кд;
  спрБ.Записать();
  спрСЛ = спрБ.Ссылка;
 иначе
  спрБ = спрСЛ.ПолучитьОбъект();
 конецЕсли;
 спрБ.Наименование = нм;
 спрБ.ЮрАдрес = юА;
 спрБ.ПчтАдрес = пА;
 спрБ.Телефоны = тл;
 спрБ.Email = мл;
 спрБ.Комментарий = "Загрузка " + ткДт;
 // Модифицируем справочники КонтактныеЛица и КонтактныеЛицаКонтрагентов
 спрБ.ОсновноеКонтактноеЛицо = дбвКЛ(спрСЛ, кЛц);
 спрБ.Записать();
 спрСЛ = спрБ.Ссылка;
 сВК = справочники.ВидыКонтактнойИнформации;
 кммнт = "Загрузка " + ткДт;
 пТКИ = перечисления.ТипыКонтактнойИнформации;
 // Модифицируем регистр сведений КонтактнаяИнформация
 дбвтКНфрмц(спрСЛ, пТКИ.Адрес, сВК.ЮрАдресКонтрагента, юА, кммнт);
 дбвтКНфрмц(спрСЛ, пТКИ.Адрес, сВК.ФактАдресКонтрагента, пА, кммнт);
 дбвтКНфрмц(спрСЛ, пТКИ.Телефон, сВК.ТелефонКонтрагента, тл, кммнт);
 дбвтКНфрмц(спрСЛ, пТКИ.АдресЭлектроннойПочты, сВК.АдресЭлектроннойПочтыКонтрагента, мл, кммнт);
 возврат спрБ;
конецФункции

// Обеспечивает обработку строк входного файла
процедура кнопкаВыполнитьНажатие(кнопка)
 если пустаяСтрока(файл) тогда предупреждение("Укажите файл"); возврат конецЕсли;
 вН = текущаяДата();
 т = новый текстовыйДокумент;
 т.Прочитать(файл);
 кс = т.КоличествоСтрок();
 спрК = справочники.Контрагенты;
 спрКЛ = справочники.КонтактныеЛица;
 спрКЛК = справочники.КонтактныеЛицаКонтрагентов;
 кд = ""; нм = ""; юА = ""; пА = ""; тл = ""; мл = ""; кЛц = "";
 спрКСГ = зпГр(спрК, "Клиенты", "1");
 для к = 1 по кс цикл
  тС = т.ПолучитьСтроку(к);
  сообщить(тС);
  если не плчтСтрк(к, тС, кд, нм, юА, пА, тл, мл, кЛц) тогда возврат конецЕсли;
  спрКБ = зпЛ(спрК, спрКСГ, кд, нм, юА, пА, тл, мл, кЛц);
 конецЦикла;
 сообщить("Готово. Время загрузки (сек): " + (текущаяДата() - вН));
конецПроцедуры

// Определяет значение реквизита Файл
процедура выбратьФайл(элемент, стандартнаяОбработка)
 нДиалог = новый диалогВыбораФайла(режимДиалогаВыбораФайла.Открытие);
 нДиалог.Фильтр = "Текстовый документ (*.txt)|*.txt";
 нДиалог.Заголовок = "Выбор файла с контрагентами";
 если нДиалог.Выбрать() тогда файл = нДиалог.ПолноеИмяФайла конецЕсли;
конецПроцедуры

// Просмотр выбранного файла
процедура файлОткрытие(элемент, стандартнаяОбработка)
 если не пустаяСтрока(файл) тогда запуститьПриложение(файл) конецЕсли;
конецПроцедуры

очиститьСообщения();
ткДт = формат(текущаяДата(), "ДЛФ = Д");

ЗАГРУЗКА НОМЕНКЛАТУРЫ

Обеспечивается обработкой ЗагрузкаТ.
Строка входного текстового файла с номенклатурой содержит следующие данные:

Данные разделяются двойной тильдой (рис. 8).

Исходные данные загрузки справочника Номенклатура

Рис. 8. Три строки файла с номенклатурой

Производитель помещается в группу Производители справочника Контрагенты; код группы G2.
Кроме того, в справочник СерийныеНомера добавляется серийный номер, код которого равен артикулу изделия. Это позволяет работать в конфигурации Гарантия с чужими изделиями, то есть с изделиями, купленными в другой организации. Серийные номера таких изделий в хранилище СН не обнаруживаются.
Данные не редактируются, а при необходимости обновляются при последующих загрузках. Для просмотра сведений об изделии 1С создает приведенную на рис. 9 форму элемента.

Редактирование элемента справочника Номенклатура 1С:Предприятие 8

Рис. 9. Форма элемента справочника Номенклатура

Справочник СерийныеНомера подчинен справочнику Номенклатура. Для просмотра списка серийных номеров (рис. 10) выбранного владельца можно использовать кнопку Перейти командной панели формы справочника номенклатуры.

Отбор по владельцу в справочнике Серийные номера 1С:Предприятие 8

Рис. 10. Серийные номера изделия с артикулом 8432

Модуль формы обработки ЗагрузкаТ содержит следующий код:

перем спрК, спрКСГ, ткДт;

// Добавление группы в справочник Контрагенты или Номенклатура
функция зпГр(спр, нмГр, кдГр)
 спрСГ = спр.НайтиПоКоду("G" + кдГр);
 если спрСГ.Пустая() тогда
  спрБ = спр.СоздатьГруппу();
  спрБ.Код = "G" + кдГр;
  спрБ.Наименование = нмГр;
  спрБ.Записать();
  спрСГ = спрБ.Ссылка;
  сообщить("Добавлена группа " + спрСГ.Наименование);
 конецЕсли;
 возврат спрСГ;
конецФункции

// Добавление элемента в справочник Контрагенты
функция дбвКнт(кнтКд, кнтНм)
 спрКС = спрК.НайтиПоКоду(кнтКд);
 если спрКС.Пустая() тогда
  спрКБ = спрК.СоздатьЭлемент();
  спрКБ.Родитель = спрКСГ;
  спрКБ.Код = кнтКд;
  спрКБ.Записать();
  спрКС = спрКБ.Ссылка;
 иначе
  спрКБ = спрКС.ПолучитьОбъект();
 конецЕсли;
 спрКБ.Наименование = кнтНм;
 спрКБ.Комментарий = "Загрузка " + ткДт;
 спрКБ.Записать();
 возврат спрКС;
конецФункции

// Возвращает один элемент текущей строки входного файла
// В качестве разделителя используется двойная тильда
функция днЛмнт(тС, п)
 лмнт = сокрЛП(лев(тС, п - 1));
 тС = сред(тС, п + 2);
 п = найти(тС, "~~");
 возврат лмнт;
конецФункции

// Извлекает из текущей строки входного файла код изделия (кд),
// его наименование (нм), код родителя (кдГр), его наименование (нмГр),
// код производителя (кнтКд) и его наименование (кнтНм)
функция плчтСтрк(к, тС, кд, нм, кдГр, нмГр, кнтКд, кнтНм)
 кнтКд = ""; кнтНм = "";
 п = найти(тС, "~~");
 если п > 0 тогда
  кд = днЛмнт(тС, п);
  если п > 0 тогда
   нм = днЛмнт(тС, п);
   если п > 0 тогда
    кдГр = днЛмнт(тС, п);
    если п > 0 тогда
     нмГр = днЛмнт(тС, п);
     если п > 0 тогда
      кнтКд = днЛмнт(тС, п);
      кнтНм = сокрЛП(тС);
     конецЕсли;
    конецЕсли;
   иначе
    нмГр = сокрЛП(тС);
   конецЕсли;
  конецЕсли;
 конецЕсли;
 если пустаяСтрока(кнтКд) тогда
  предупреждение("Строка " + к + ". Неверный формат данных");
  возврат ложь;
 конецЕсли;
 возврат истина;
конецФункции

// Добавляет или изменяет сведения об изделии
функция зпЛ(спр, спрСГ, кд, нм, кнтКд, кнтНм)
 спрСЛ = спр.НайтиПоКоду(кд);
 если спрСЛ.Пустая() тогда
  спрБ = спр.СоздатьЭлемент();
  спрБ.Родитель = спрСГ;
  спрБ.Код = кд;
  спрБ.Записать();
  спрСЛ = спрБ.Ссылка;
 иначе
  спрБ = спрСЛ.ПолучитьОбъект();
 конецЕсли;
 спрБ.Наименование = нм;
 спрБ.Артикул = кд;
 спрБ.ОсновнойПоставщик = дбвКнт(кнтКд, кнтНм);
 спрБ.Комментарий = "Загрузка " + ткДт;
 спрБ.Записать();
 возврат спрБ.ссылка;
конецФункции

// Добавляет в справочник СерийныеНомера СН, код которого равен артикулу изделия
функция дбСН(спрСН, снВ, тврС, спрКС)
 спрСНБ = спрСН.СоздатьЭлемент();
 спрСНБ.Владелец = тврС;
 спрСНБ.Покупатель = спрКС;
 спрСНБ.Код = снВ;
 спрСНБ.ДатаРеализации = текущаяДата();
 спрСНБ.Цена = 0;
 спрСНБ.Записать();
 возврат спрСНБ.Ссылка;
конецФункции

// Обеспечивает обработку строк входного файла
процедура кнопкаВыполнитьНажатие(кнопка)
 если пустаяСтрока(файл) тогда предупреждение("Укажите файл"); возврат конецЕсли;
 вН = текущаяДата();
 т = новый текстовыйДокумент;
 т.Прочитать(файл);
 кс = т.КоличествоСтрок();
 спрН = справочники.Номенклатура;
 спрК = справочники.Контрагенты;
 кд = ""; нм = ""; кдГр = ""; нмГр = ""; кнтКд = ""; кнтНм = "";
 спрКСГ = зпГр(спрК, "Производители", "2");
 для к = 1 по кс цикл
  тС = т.ПолучитьСтроку(к);
  сообщить(тС);
  если не плчтСтрк(к, тС, кд, нм, кдГр, нмГр, кнтКд, кнтНм) тогда возврат конецЕсли;
  спрНСГ = зпГр(спрН, нмГр, кдГр);
  спрНС = зпЛ(спрН, спрНСГ, кд, нм, кнтКд, кнтНм);
  спрСН = справочники.СерийныеНомера;
  если спрСН.НайтиПоКоду(кд).Пустая() тогда
   дбСН(спрСН, кд, спрНС, справочники.Контрагенты.ПустаяСсылка());
  конецЕсли;
 конецЦикла;
 сообщить("Готово. Время загрузки (сек): " + (текущаяДата() - вН));
КонецПроцедуры

// Определяет значение реквизита Файл
процедура выбратьФайл(элемент, стандартнаяОбработка)
 нДиалог = новый диалогВыбораФайла(режимДиалогаВыбораФайла.Открытие);
 нДиалог.Фильтр = "Текстовый документ (*.txt)|*.txt";
 нДиалог.Заголовок = "Выбор файла с номенклатурой";
 если нДиалог.Выбрать() тогда файл = нДиалог.ПолноеИмяФайла конецЕсли;
конецПроцедуры

// Просмотр выбранного файла
процедура файлОткрытие(элемент, стандартнаяОбработка)
 если не пустаяСтрока(файл) тогда запуститьПриложение(файл) конецЕсли;
конецПроцедуры

очиститьСообщения();
ткДт = формат(текущаяДата(), "ДЛФ = Д");

ЗАГРУЗКА СЕРИЙНЫХ НОМЕРОВ

Обеспечивается обработкой ЗагрузкаСН.
Строка входного файла содержит следующие данные:

Данные разделяются двойной тильдой (рис. 11).

Исходные данные загрузки справочника Серийные номера

Рис. 11. Три строки файла с серийными номерами

Цена продажи изделия в тестовом варианте генерируется как случайное число из диапазона 100 – 500.
Загрузка СН выполняется после загрузки контрагентов и номенклатуры. Если при загрузке СН изделие-владелец не найдено или не найден покупатель (поиск ведется по коду), то формируются соответствующие сообщения.
Просмотр данных обеспечивает форма элемента справочника (рис. 12).

Редактирование элемента справочника Серийные номера 1С:Предприятие 8

Рис. 12. Форма элемента справочника СерийныеНомера

Загрузку серийных номеров обеспечивает следующий, находящийся в модуле формы обработки ЗагрузкаСН код:

перем рзд;

// Возвращает один элемент текущей строки входного файла
// В качестве разделителя используется двойная тильда
функция днЛмнт(тС, п, нПслдн = истина)
 лмнт = сокрЛП(лев(тС, п - 1));
 тС = сред(тС, п + 2);
 п = ?(нПслдн, найти(тС, рзд), 1);
 возврат лмнт;
конецФункции

// Извлекает из текущей строки входного файла серийный номер (снЗнч),
// дату реализации (дт), код номенклатуры (кд), гарантийный срок (грнт),
// код покупателя (кнтКд) и Id расходной накладной (дКд)
функция плчтСтрк(к, тС, снЗнч, дт, кд, грнт, кнтКд, дКд)
 кнтКд = "";
 грнт = 0;
 п = найти(тС, рзд);
 если п > 0 тогда
  снЗнч = днЛмнт(тС, п);
  если п > 0 тогда
   дт = днЛмнт(тС, п);
   дт = стрЗаменить(дт, ".", "");
   дт = сред(дт, 5) + сред(дт, 3, 2) + лев(дт, 2);
   если п > 0 тогда
    кд = днЛмнт(тС, п);
    если п > 0 тогда
     грнт = днЛмнт(тС, п);
     если п > 0 тогда
      кнтКд = днЛмнт(тС, п, ложь);
      если п > 0 тогда
       дКд = сокрЛП(тС);
       п = найти(грнт, " ");
       грнт = лев(грнт, п - 1);
      конецЕсли;
     конецЕсли;
    конецЕсли;
   конецЕсли;
  конецЕсли;
 конецЕсли;
 если пустаяСтрока(дКд) тогда
  сообщить("Строка " + к + ". Неверный формат данных", статусСообщения.Внимание);
  возврат ложь;
 конецЕсли;
 возврат истина;
конецФункции

// Добавляет или изменяет сведения о серийном номере
функция зпЛ(з, спрСН, спрНС, спрКС, снЗнч, дт, грнт, цн, дКд)
 з.установитьПараметр("сн", снЗнч);
 з.установитьПараметр("влд", спрНС);
 р = з.выполнить();
 если р.пустой() тогда
  спрСНБ = спрСН.СоздатьЭлемент();
  спрСНБ.Владелец = спрНС;
 иначе
  в = р.выбрать();
  в.следующий();
  спрСНБ = в.ссылка.получитьОбъект();
 конецЕсли;
 спрСНБ.Код = снЗнч;
 спрСНБ.ДатаРеализации = дата(дт);
 спрСНБ.Покупатель = спрКС;
 спрСНБ.Гарантия = грнт;
 спрСНБ.Цена = цн;
 спрСНБ.НомерДок = дКд;
 спрСНБ.Записать();
конецФункции

// Обеспечивает обработку строк входного файла
процедура кнопкаВыполнитьНажатие(Кнопка)
 если пустаяСтрока(файл) тогда предупреждение("Не выбран файл"); возврат конецЕсли;
 очиститьСообщения();
 вН = текущаяДата();
 т = новый текстовыйДокумент;
 т.Прочитать(файл);
 кс = т.КоличествоСтрок();
 сообщить("Всего строк в исходном файле: " + кс);
 спрСН = справочники.СерийныеНомера;
 спрН = справочники.Номенклатура;
 спрК = справочники.Контрагенты;
 снЗнч = ""; дт = ""; кд = ""; грнт = 0; кнтКд = ""; дКд = "";
 чПС = 0; чПС2 = 0; чПС3 = 0;
 гсч = новый ГенераторСлучайныхЧисел;
 з = новый запрос;
 з.текст = "выбрать ссылка из справочник.серийныеНомера где код = &сн и владелец = &влд";
 для к = 1 по кс цикл
  тС = т.ПолучитьСтроку(к);
  сообщить(тС);
  если не плчтСтрк(к, тС, снЗнч, дт, кд, грнт, кнтКд, дКд) тогда
   чПС = чПС + 1;
   продолжить;
  конецЕсли;
  спрНС = спрН.НайтиПоКоду(кд);
  если спрНС.Пустая() тогда
   сообщить("Не найдено изделие с кодом " + кд);
   чПС2 = чПС2 + 1;
   продолжить;
  конецЕсли;
  спрКС = спрК.НайтиПоКоду(кнтКд);
  если спрКС.Пустая() тогда
   сообщить("Товар с кодом " + кд + ": не найден покупатель с кодом " + кнтКд);
   чПС3 = чПС3 + 1;
   продолжить;
  конецЕсли;
  зпЛ(з, спрСН, спрНС, спрКС, снЗнч, дт, грнт, гсч.СлучайноеЧисло(100, 500), дКд);
 конецЦикла;
 сообщить("Готово. Время загрузки (сек): " + (текущаяДата() - вН));
 если чПС > 0 тогда сообщить("Число плохих строк: " + чПС) конецЕсли;
 если чПС2 > 0 тогда сообщить("Не найдено изделий: " + чПС2) конецЕсли;
 если чПС3 > 0 тогда сообщить("Не найдено покупателей: " + чПС3) конецЕсли;
конецПроцедуры

// Определяет значение реквизита Файл
процедура выбратьФайл(элемент, стандартнаяОбработка)
 нДиалог = новый диалогВыбораФайла(режимДиалогаВыбораФайла.Открытие);
 нДиалог.Фильтр = "Текстовый документ (*.txt)|*.txt";
 нДиалог.Заголовок = "Выбор файла с номенклатурой";
 если нДиалог.Выбрать( ) тогда
  файл = нДиалог.ПолноеИмяФайла;
 конецЕсли;
конецПроцедуры

// Просмотр выбранного файла
процедура файлОткрытие(элемент, стандартнаяОбработка)
 если не пустаяСтрока(файл) тогда запуститьПриложение(файл) конецЕсли;
конецПроцедуры

очиститьСообщения();
рзд = "~~";

Особенность загрузки в том, что значение СН (поле Код справочника СН) не является уникальным. Поэтому вместо поиска по коду используется запрос к справочнику СН с отбором по коду и влядельцу.

ОБЩИЙ МОДУЛЬ ВСН

Общий модуль вСН снабжен свойством Внешнее соединение. Это позволяет вызывать экспортируемые функции модуля в конфигураци-приемнике, если в ней установлено внешнее соединение с хранилищем СН.
В модуле две функции:

функция получитьСЗ(сн) экспорт
 тбр = новый структура("Отбор, СтрокаПоиска, ВыборГруппИЭлементов", "Код", сн, использованиеГруппИЭлементов.Элементы);
 сЗ = справочники.СерийныеНомера.ПолучитьДанныеВыбора(тбр);
 возврат сЗ;
конецФункции

функция выборСН(кд) экспорт
 т = "выбрать первые 500 ссылка как СН,
 | справочник.СерийныеНомера.владелец.артикул как Артикул,
 | справочник.СерийныеНомера.владелец как Изделие, номерДок как Документ, датаРеализации как Дата,
 | покупатель.наименование как Покупатель, гарантия, Цена, 0 как Остаток
 | из справочник.СерийныеНомера
 | где не пометкаУдаления и код подобно &кд";
 з = новый запрос;
 з.текст = т;
 з.УстановитьПараметр("кд", "%" + кд + "%");
 возврат з.Выполнить();
конецФункции

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

КОНФИГУРАЦИЯ ГАРАНТИЯ

Используемая в примере часть конфигурации-приемника (конфигурации Гарантия) показана на рис. 13.

Конфигурация Гарантия в 1С:Предприятие 8

Рис. 13. Используемая в примере часть конфигурации Гарантия

НАЧАЛЬНОЕ ЗАПОЛНЕНИЕ БАЗЫ ДАННЫХ ГАРАНТИЯ

Выполняется обработками Начало и Дефекты.

МОДУЛЬ ФОРМЫ ОБРАБОТКИ НАЧАЛО

процедура кнопкаВыполнитьНажатие(кнопка)
 кммнт = "Ввод начальных данных " + текущаяДата();
 кд = "000000001";
 // Организация
 сО = справочники.Организации.НайтиПоКоду(кд);
 если сО.Пустая() тогда
  сБ = справочники.Организации.СоздатьЭлемент();
  сБ.Код = кд;
  сБ.Наименование = "Среди миров";
  сБ.Записать();
  сО = сБ.Ссылка;
 конецЕсли;
 юА = "107143, Москва, Млечный путь, д. 114";
 пА = юА;
 сВК = справочники.ВидыКонтактнойИнформации;
 пТКИ = перечисления.ТипыКонтактнойИнформации;
 гарантия.дбвтКНфрмц(сО, пТКИ.Адрес, сВК.ЮрАдресОрганизации, юА, кммнт);
 гарантия.дбвтКНфрмц(сО, пТКИ.Адрес, сВК.ФактАдресОрганизации, пА, кммнт);
 гарантия.дбвтКНфрмц(сО, пТКИ.Телефон, сВК.ТелефонОрганизации, "8-496-917-82-27", кммнт);
 гарантия.дбвтКНфрмц(сО, пТКИ.Телефон, сВК.ФаксОрганизации, "8-497-917-57-23", кммнт);
 гарантия.дбвтКНфрмц(сО, пТКИ.АдресЭлектроннойПочты, сВК.СлужебныйАдресЭлектроннойПочтыПользователя, "sb@addr.ru", кммнт);
 // Склад
 сСкл = справочники.Склады.НайтиПоКоду(кд);
 если сСкл.Пустая() тогда
  сБ = справочники.Склады.СоздатьЭлемент();
  сБ.Код = кд;
  сБ.Наименование = "Склад приема";
  сБ.Записать();
  сСкл = сБ.Ссылка;
 конецЕсли;
 // Константы
 если константы.Организация.Получить().Пустая() тогда константы.Организация.Установить(сО) конецЕсли;
 если константы.СкладПриема.Получить().Пустая() тогда константы.СкладПриема.Установить(сСкл) конецЕсли;
 предупреждение("Готово");
конецПроцедуры

Значения констант Организация и СкладПриема подставляются в соответствующие реквизиты документа ПриемИзделий при создании нового документа.
Связанная с организацией Контактная информация добавляется в одноименный регистр сведений следующей процедурой общего модуля гарантия:

// Модифицирует регистр сведений КонтактнаяИнформация
процедура дбвтКНфрмц(спрСЛ, тпКИ, вдКИ, пр, кммнт) экспорт
 мнЗп = регистрыСведений.КонтактнаяИнформация.СоздатьМенеджерЗаписи();
 мнЗп.Объект = спрСЛ;
 мнЗп.Тип = тпКИ;
 мнЗп.Вид = вдКИ;
 мнЗп.Представление = пр;
 мнЗп.Комментарий = кммнт;
 мнЗп.Период = '20120101';
 мнЗп.Записать();
конецПроцедуры

Эта информация используется при создании отчетов, например Акта приема-передачи документа ПриемИзделий.

МОДУЛЬ ФОРМЫ ОБРАБОТКИ ДЕФЕКТЫ

Имеющийся в модуле код обеспечивает начальное заполнение справочника Дефекты, содержащего перечень возможных дефектов изделий. Справочник используется при создании документа ПриемИзделий.
Кроме того в модуле имеется процедура очистки справочника Дефекты.

// Добавляет в справочник группу и элементы, беря их наименование из массива дМас
процедура добавитьМассив(сД, грИмя, дМас)
 сДГС = сД.НайтиПоНаименованию(грИмя);
 если сДГС.Пустая() тогда
  сДО = сД.СоздатьГруппу();
  сДО.Наименование = грИмя;
  сДО.Записать();
  сДГС = сДО.ссылка;
 конецЕсли;
 для каждого нм из дМас цикл
  сДС = сД.НайтиПоНаименованию(нм, , сДГС);
  если сДС.Пустая() тогда
   сДО = сД.СоздатьЭлемент();
   сДО.Родитель = сДГС;
   сДО.Наименование = нм;
   сДО.Записать();
  конецЕсли;
 конецЦикла;
конецПроцедуры

процедура кнопкаВыполнитьНажатие(кнопка)
 очиститьСообщения();
 дГрМас = новый массив(4);
 дМас0 = новый массив(13);
 дМас1 = новый массив(8);
 дМас2 = новый массив(26);
 дМас3 = новый массив(2);
 //
 дГрМас[0] = "МВ";
 дГрМас[1] = "VC";
 дГрМас[2] = "Платформы";
 дГрМас[3] = "БП";
 //
 дМас0[0] = "Нет звука";
 дМас0[1] = "Не стартует";
 дМас0[2] = "Периодически перезагружается";
 дМас0[3] = "Не работает PS/2";
 дМас0[4] = "Не работает слот памяти";
 дМас0[5] = "Не работает HDD";
 дМас0[6] = "Не работает LAN";
 дМас0[7] = "Не работает SATA-разъем";
 дМас0[8] = "Не работает один из видеовыходов";
 дМас0[9] = "Не работает COM-порт";
 дМас0[10] = "Не работает LPT";
 дМас0[11] = "Не работает USB-выход";
 дМас0[12] = "Не работает PCI-слот";
 //
 дМас1[0] = "Артефакты";
 дМас1[1] = "Не стартует";
 дМас1[2] = "Не устанавливаются драйвера";
 дМас1[3] = "Не работает HDMI-выход";
 дМас1[4] = "Не работает VGA-выход";
 дМас1[5] = "Не работает DVI-выход";
 дМас1[6] = "Не работает DisplayPopt-выход";
 дМас1[7] = "С прогревом отключается";
 //
 дМас2[0] = "Артефакты";
 дМас2[1] = "Не включается";
 дМас2[2] = "С прогревом отключается";
 дМас2[3] = "Нет звука";
 дМас2[4] = "Нет подсветки матрицы";
 дМас2[5] = "Нет изображения";
 дМас2[6] = "Не работает COM-порт";
 дМас2[7] = "Не работает USB2";
 дМас2[8] = "Не работает VGA-выход";
 дМас2[9] = "Не работает DVI-выход";
 дМас2[10] = "Не работает HDMI-выход";
 дМас2[11] = "Не работает Блок питания";
 дМас2[12] = "Не работает Сенсорный экран";
 дМас2[13] = "Не читает оптические диски";
 дМас2[14] = "Не работает клавиатура";
 дМас2[15] = "Не работает мышь";
 дМас2[16] = "Не ставится ОС";
 дМас2[17] = "Не работает LAN";
 дМас2[18] = "Не устанавливаются драйвера";
 дМас2[19] = "Не работает Wi-Fi";
 дМас2[20] = "Не работает TV-тюнер";
 дМас2[21] = "Не работает звуковой выход";
 дМас2[22] = "Не работает звуковой вход";
 дМас2[23] = "Не работает видеокамера";
 дМас2[24] = "Не работает микрофон";
 дМас2[25] = "Не видит HDD";
 //
 дМас3[0] = "Не стартует";
 дМас3[1] = "Не выдаёт необходимого напряжения";
 //
 сД = справочники.Дефекты;
 добавитьМассив(сД, дГрМас[0], дМас0);
 добавитьМассив(сД, дГрМас[1], дМас1);
 добавитьМассив(сД, дГрМас[2], дМас2);
 добавитьМассив(сД, дГрМас[3], дМас3);
 предупреждение("Готово");
конецПроцедуры

// Очистка справочника Дефекты
процедура основныеДействияФормыОчистить(кнопка)
  св = справочники.Дефекты.Выбрать();
  н = 0;
  пока св.Следующий() цикл
   н = н + 1;
   со = св.ПолучитьОбъект();
   со.Удалить();
  конецЦикла;
  если н > 0 тогда сообщить("Удалено элементов справочника Дефекты изделий: " + н) конецЕсли;
конецПроцедуры

ВВОД ПАРАМЕТРОВ СОЕДИНЕНИЯ

Выполняется обработкой, форма которой приведена на рис. 14.

Форма обработки ввода параметров внешнего соединения 1С:Предприятие 8

Рис. 14. Форма обработки ввода параметров соединения

Кроме того, при записи параметров соединения (константы ПараметрыСоединения) обработка устанавливает соединение приемника с источником (если правильно указаны параметры соединения). При наличии внешнего соединения флажок Флаг соединения установлен (переменная стСднн имеет значение Истина). Также предусмотрена возможность разрыва ранее установленного внешнего соединения.
Весь код обработки расположен в модуле ее формы:

процедура основныеДействияФормыСтвтСднн(кнопка)
 если пустаяСтрока(прмСдн) тогда
  предупреждение("Не заданы параметры соединения");
 иначе
  если стСднн тогда
   предупреждение("Нужно разорвать соединение")
  иначе
   константы.ПараметрыСоединения.Установить(прмСдн);
   попытка
    glCntr = новый COMObject("V82.COMConnector");
    глВнешнееСоединение = glCntr.Connect(прмСдн);
    предупреждение("Установлено");
    стСднн = истина;
   исключение
    сообщить(описаниеОшибки());
   конецПопытки;
  конецЕсли;
 конецЕсли;
конецПроцедуры

процедура основныеДействияФормыРазрыв(кнопка)
 если стСднн тогда
  глВнешнееСоединение = неопределено;
  стСднн = ложь;
 конецЕсли;
конецПроцедуры

процедура приОткрытии()
 прмСдн = константы.ПараметрыСоединения.Получить();
 если пустаяСтрока(прмСдн) тогда
  предупреждение("Не задана константа ПараметрыСоединения");
 иначе
  стСднн = не глВнешнееСоединение = неопределено
 конецЕсли;
конецПроцедуры

МОДУЛЬ ОБЫЧНОГО ПРИЛОЖЕНИЯ

В модуле обычного приложения при его запуске устанавливается соединение приемника с источником и определяется текущий пользователь. В первом случае определяется значение переменной глВнешнееСоединение, а во втором – значение переменной глТекущийПользователь. Обе переменные обладают глобальной видимостью.
Строку с параметрами соединения хранит константа ПараметрыСоединения.

перем глТекущийПользователь экспорт;
перем глВнешнееСоединение экспорт;
перем глФД экспорт;
перем глДтНач экспорт;

процедура приНачалеРаботыСистемы()
 определитьТекущегоПользователя();
 прмСдн = константы.ПараметрыСоединения.Получить();
 если пустаяСтрока(прмСдн) тогда
  сообщить("Не заданы параметры соединения");
  глВнешнееСоединение = неопределено;
 иначе
  glCntr = новый COMObject("V82.COMConnector");
  попытка
   глВнешнееСоединение = glCntr.Connect(прмСдн);
  исключение
  конецПопытки;
 конецЕсли;
конецПроцедуры

процедура определитьТекущегоПользователя( )
 имяПолз = имяПользователя( );
 полнИмя = полноеИмяПользователя( );
 полнИмя = ?(пустаяСтрока(полнИмя), имяПолз, полнИмя);
 глТекущийПользователь = справочники.Пользователи.НайтиПоКоду(имяПолз);
 если глТекущийПользователь = справочники.Пользователи.ПустаяСсылка( ) тогда
  объектПользователь = справочники.Пользователи.СоздатьЭлемент( );
  объектПользователь.Код = имяПолз;
  объектПользователь.Наименование = полнИмя;
  объектПользователь.Записать( );
  глТекущийПользователь = объектПользователь.Ссылка;
 конецЕсли;
конецПроцедуры

глФД = "ДЛФ = Д";
глДтНач = '00010101';

ДОКУМЕНТ ПРИЕМ ИЗДЕЛИЙ

Фиксирует изделия, принятые для гарантийного обслуживания.

ФОРМЫ ДОКУМЕНТА И СПИСКА

Форма документа приведена на рис. 15, а форма списка на рис. 16.

Редактирование документа Прием изделий 1С:Предприятие 8

Рис. 15. Форма документа ПриемИзделий

Список документов Прием изделий

Рис. 16. Форма списка документа ПриемИзделий

Сумма документа вычисляется перед его записью.

процедура передЗаписью(отказ, режимЗаписи, режимПроведения)
 суммаДокумента = 0;
 для каждого с из изделия цикл
  суммаДокумента = суммаДокумента + с.цена * с.количество
 конецЦикла;
конецПроцедуры

ПРОВЕДЕНИЕ ДОКУМЕНТА

При проведении документа ПриемИзделий модифицируется регистр накопления ИзделияНаСкладах:

процедура обработкаПроведения(отказ, режим)
 отказ = истина;
 если склад.Пустая() тогда предупреждение("Не указан склад"); возврат конецЕсли;
 для каждого с из изделия цикл
  если с.Номенклатура.Пустая() тогда предупреждение("Есть строка с пустой номенклатурой"); возврат конецЕсли;
  если с.СерийныйНомер.Пустая() тогда предупреждение("Есть строка с пустым серийным номером"); возврат конецЕсли;
 конецЦикла;
 отказ = ложь;
 // Приход
 движения.ИзделияНаСкладах.Очистить();
 для каждого с из изделия цикл
  движение = движения.ИзделияНаСкладах.Добавить();
  движение.ВидДвижения = видДвиженияНакопления.Приход;
  движение.Период = дата;
  движение.Склад = склад;
  движение.Номенклатура = с.Номенклатура;
  движение.СерийныйНомер = с.СерийныйНомер;
  движение.Количество = с.Количество;
 конецЦикла;
конецПроцедуры

ПЕЧАТЬ ДОКУМЕНТА

Печать акта приема-передачи выполняется следующей процедурой модуля документа ПриемИзделий:

процедура печатьАктаПриемаПередачи() экспорт
 тД = новый ТабличныйДокумент;
 мкт = получитьМакет("АктПриемаПередачи");
 ом = мкт.ПолучитьОбласть("заг");
 прм = ом.Параметры;
 прм.Орг = организация;
 прм.Кнт = клиент;
 номерБезН = гарантия.удалитьНули(номер);
 зг = "Акт приёма-передачи изделий";
 прм.зг = зг + " на гарантийное обслуживание № " + номерБезН + " от " + формат(дата, "ДЛФ = Д");
 тД.Вывести(ом);
 ом = мкт.ПолучитьОбласть("тв");
 прм = ом.Параметры;
 нм2 = 0;
 тз = изделия.Выгрузить();
 для каждого тв из тз цикл
  нм2 = нм2 + 1;
  прм.нм2 = нм2;
  твр = тв.Номенклатура;
  прм.тв = твр.НаименованиеПолное;
  прм.тв2 = твр;
  прм.рткл = твр.Артикул;
  прм.сн = тв.СерийныйНомер;
  прм.кл = тв.Количество;
  прм.производитель = твр.ОсновнойПоставщик;
  прм.здф = тв.ЗаявленныйДефект;
  прм.кммнт = тв.Комментарий;
  тД.Вывести(ом);
 конецЦикла;
 ом = мкт.ПолучитьОбласть("подп");
 тД.Вывести(ом);
 тД.защита = истина;
 тД.Показать(зг);
 фрмД = получитьФорму();
 пВФайл = фрмД.ЭлементыФормы.ПечатьВФайл.значение;
 гарантия.печатьВФайл(тД, клиент, номерБезН, зг, "прием", пВФайл);
конецПроцедуры

Пример печатной формы показан на рис. 17.

Пример отчета Акт приема-передачи изделий

Рис. 17. Акт приема-передачи изделий

Номер акта приема-передачи – это номер документа без ведущих нулей, удаляемых функцией общего модуля Гарантия.

// Удаляет в строке ведущие нули
функция удалитьНули(номер) экспорт
 нмр = сокрЛП(номер);
 пока лев(нмр, 1) = "0" цикл нмр = сред(нмр, 2) конецЦикла;
 возврат нмр
конецФункции

Печать табличного документа в файл выполняется процедурой печатьВФайл общего модуля Гарантия.

// Обеспечивает запись печатной формы в XLS-файл
процедура печатьВФайл(тД, контрагент, номерБезН, зг, зг2, пВФайл) экспорт
 если пВФайл тогда
  пт = сокрП(константы.КаталогПечати.Получить());
  если пустаяСтрока(пт) тогда
   предупреждение("Не задана константа Каталог печати"); возврат
  иначе
   пт = пт + ?(прав(пт, 1) = "\", "", "\")
  конецЕсли;
  кнтКр = сокрЛП(лев(контрагент, 10)) + "_";
  файл = пт + кнтКр + зг2 + номерБезН + ".XLS";
  тД.Записать(файл, типФайлаТабличногоДокумента.XLS);
  сообщить(зг + " записан" + " в файл " + файл)
 конецЕсли;
конецПроцедуры

ПОПОЛНЕНИЕ ТАБЛИЧНОЙ ЧАСТИ ДОКУМЕНТА

Происходит после нажатия на кнопку CН или чСН формы документа ПриемИзделий.
В первом случае потребуется ввести серийный номер (СН) или его начальные символы (рис. 18), во втором случае поиск серийного номера выполняется по введенной подстроке средствами обработки отбора по части СН.

Указаны начальные искомого символы серийного номера

Рис. 18. Пополнение табличной части документа по начальным символам СН

Для ввода СН можно употребить сканер штрих-кода.
Приведенный на рис. 18 диалог формирует функция заполнитьПоСН, вызываемая после нажатия на кнопку СН формы документа. Эта же функция обрабатывает введенную подстроку поиска, возвращая в случае удачи ссылку на добавленную строку табличной части Изделия:

// Возвращает неопределено или ссылку на добавленную строку табличной части Изделия
функция заполнитьПоСН(изделия, бкт) экспорт
 перем сн;
 ввестиСтроку(сн, "Введите СН или его начальные символы");
 если пустаяСтрока(сн) тогда возврат неопределено конецЕсли;
 сн = сокрЛП(сн);
 спрСН = справочники.СерийныеНомера;
 снСП = спрСН.ПустаяСсылка();
 тбр = новый структура("Отбор, СтрокаПоиска, ВыборГруппИЭлементов", "Код", сн, использованиеГруппИЭлементов.Элементы);
 // Ищем прежде в базе Гарантия
 сЗ = спрСН.ПолучитьДанныеВыбора(тбр);
 вБД = ложь;
 если сЗ = неопределено тогда
  // В случае неудачи ищем прежде в хранилище СН
  вБД = истина;
  сЗ = глВнешнееСоединение.вСН.получитьСЗ(сн);
  если сЗ = неопределено тогда
   предупреждение("Хранилище СН: не найден серийный номер " + сн); возврат неопределено
  конецЕсли;
 конецЕсли;
 если сЗ.Количество() = 1 тогда
  // Найден один элемент
  снС = сЗ.получить(0).значение;
 иначе
  // Найдено несколько элементов
  снС = выбратьИзСписка(сн, сЗ, вБД, снСП);
  если снС.пустая() тогда возврат неопределено конецЕсли;
 конецЕсли;
 если вБД тогда
  // вБД есть истина, если элемент взят из хранилища СН
  снС = добавитьИзВБ(сокрЛП(снС.код), снС, снСП);
  если снС.пустая() тогда возврат неопределено конецЕсли;
 иначе
  // Использована база Гарантия
  сообщить("Использован RMA-СН");
 конецЕсли;
 // Пополняем табличную часть Изделия
 твр = изделия.Добавить();
 тврС = снС.Владелец;
 твр.Номенклатура = тврС;
 твр.СерийныйНомер = снС;
 цн = снС.Цена;
 твр.Цена = ?(цн = 0, 1.0, цн);
 твр.Количество = 1;
 фрм = бкт.получитьФорму();
 фрм.элементыФормы.изделия.ТекущаяСтрока = твр;
 возврат твр;
конецФункции

По введенной подстроке в базе Гарантия по коду в справочнике серийных номеров ищется подходящий СН. Если найден один элемент, то он используется для пополнения табличной части Изделия, если элементов, отвечающих отбору, несколько, то выводится их список (рис. 19).

Серийные номера, отобранные по его начальным символам

Рис. 19. Выбор СН из списка

Этот список формируется как таблица значений в форме обработки ВыборСНИзТЗ. Вызов обработки и возврат результата выполняет следующая функция общего модуля Гарантия:

функция выбратьИЗСписка(сн, сЗ, вБД, снСП)
 тзОтбор = создатьТЗОтбор(вБД);
 для каждого с из сЗ цикл
  сн = с.Значение;
  сТ = тзОтбор.Добавить();
  // В случае хранилища СН значение СН определяем равным коду текущего СН
  сТ.СН = ?(вБД, сн.код, сн);
  влд = сн.владелец;
  сТ.Артикул = влд.Артикул;
  сТ.Изделие = влд.Наименование;
  сТ.Дата = формат(сн.ДатаРеализации, глФД);
  сТ.Покупатель = сн.Покупатель.Наименование;
  сТ.Гарантия = сн.Гарантия;
  сТ.Цена = сн.Цена;
 конецЦикла;
 тзОтбор.свернуть("СН, Артикул, Изделие, Дата, Покупатель, Цена, Гарантия", "Остаток");
 сИП = новый структура("тзОтбор, надписьСН, вБД", тзОтбор, ?(вБД, "Выбор из хранилища СН. ", "") + "Строка отбора: " + сн, вБД);
 фрм = обработки.ВыборСНИзТЗ.ПолучитьФорму();
 фрм.сИП = сИП;
 фрм.индекс = -1;
 фрм.изменятьСпособОтображенияОкна = изменениеСпособаОтображенияОкна.Разрешить;
 фрм.ОткрытьМодально();
 если фрм.индекс = -1 тогда возврат снСП конецЕсли;
 возврат сЗ.Получить(фрм.индекс).Значение;
конецФункции

Функции создатьТЗОтбор и всПостроитьОписаниеТипа, создающие таблицу значений, передаваемую обработке выбора СН, также помещены в общий модуль Гарантия:

функция создатьТЗОтбор(вБД) экспорт
 т = новый таблицаЗначений;
 опТС = всПостроитьОписаниеТипа("Строка");
 опТЧ = всПостроитьОписаниеТипа("Число", 10, 2);
 если вБД тогда
  т.Колонки.Добавить("СН", опТС);
 иначе
  т.Колонки.Добавить("СН", всПостроитьОписаниеТипа("СправочникСсылка.СерийныеНомера"));
 конецЕСли;
 т.Колонки.Добавить("Артикул", опТС);
 т.Колонки.Добавить("Изделие", опТС);
 т.Колонки.Добавить("Дата", опТС);
 т.Колонки.Добавить("Покупатель", опТС);
 т.Колонки.Добавить("Гарантия", опТЧ);
 т.Колонки.Добавить("Цена", опТЧ);
 т.Колонки.Добавить("Остаток", опТЧ);
 возврат т;
конецФункции
//
функция всПостроитьОписаниеТипа(имяТипа, длина = 0, точность = 0, частиДаты = "") экспорт
 перем массив, квалификаторСтроки, квалификаторЧисла, квалификаторДаты;
 // Определяем прежде значения квалификаторов типа имяТипа
 // если тип параметра отличен от типа Строка, Число или Дата,
 // то значения квалификаторов будут иметь тип Неопределено
 если имяТипа = "Строка" тогда
  // Системное перечисление ДопустимаяДлина имеет 2 значения: Переменная и Фиксированная
  квалификаторСтроки = новый квалификаторыСтроки(Длина, ДопустимаяДлина.Переменная);
 иначеЕсли имяТипа = "Число" тогда
  // Системное перечисление ДопустимыйЗнак имеет 2 значения: Любой и Неотрицательный
  квалификаторЧисла = новый квалификаторыЧисла(длина, точность, допустимыйЗнак.Любой);
 иначеЕсли имяТипа = "Дата" тогда
  // Системное перечисление ЧастиДаты имеет значения Время, Дата и ДатаВремя
  если типЗнч(ЧастиДаты) = тип("ЧастиДаты") тогда
   квалификаторДаты = новый квалификаторыДаты(частиДаты);
  иначе
   квалификаторДаты = новый квалификаторыДаты(частиДаты.Дата);
  конецЕсли;
 конецЕсли;
 // Первый параметр метода описаниеТипов - одномерный массив с элементом типа имяТипа
 м = новый массив;
 м.Добавить(тип(имяТипа));
 возврат новый описаниеТипов(м, квалификаторДаты, квалификаторСтроки, квалификаторЧисла);
конецФункции

ОБРАБОТКА ВЫБОРА СН

Обработка ВыборСНИзТЗ имеет 4 реквизита (рис. 20).

Обработка выбора серийного номера: реквизиты

Рис. 20. Реквизиты обработки выбора СН

Реквизиты заполняются по полям структуры сИП, формируемой перед обращением к обработке и передаваемой затем форме обработки в качестве параметра (см. код вышеприведенной функции выбратьИЗСписка). Имя параметра должно быть объявлено в модуле обработки:

перем сИП экспорт;

После выбора в модуле формы обработки реквизиту Индекс присваивается значение индекса выбранной строки.
Код модуля формы обработки ВыборСНИзТЗ:

перем эфтп;

процедура кнопкаВыполнитьНажатие(кнопка)
 индекс = тзОтбор.Индекс(эфтп.ТекущаяСтрока);
 этаФорма.Закрыть();
конецПроцедуры

процедура тпВыбор(Элемент, выбраннаяСтрока, Колонка, СтандартнаяОбработка)
 индекс = тзОтбор.Индекс(выбраннаяСтрока);
 этаФорма.Закрыть();
конецПроцедуры

процедура остаткиПриИзменении(элемент)
 эфтп.колонки["Остаток"].Видимость = остатки;
конецПроцедуры

процедура передОткрытием(отказ, стандартнаяОбработка)
 если сИП = неопределено тогда возврат конецЕсли;
 // Определяем значения реквизитов обработки
 сИП.Свойство("тзОтбор", тзОтбор);
 сИП.Свойство("надписьСН", надписьСН);
 сИП.Свойство("вБД", изХранилищаСН);
конецПроцедуры

процедура приОткрытии()
 если сИП = неопределено тогда возврат конецЕсли;
 элементыФормы.НадписьСН.Заголовок = надписьСН;
 эфтп.СоздатьКолонки();
 для каждого клнк из эфтп.Колонки цикл клнк.ТолькоПросмотр = истина конецЦикла;
 если изХранилищаСН тогда
  элементыФормы.остатки.Видимость = ложь
 иначе
  гарантия.остаткиРасчет(тзОтбор)
 конецЕсли;
 эфтп.колонки.Остаток.Видимость = ложь;
конецПроцедуры

эфтп = элементыФормы.тп;

При установки флажка Показать остатки (реквизит Остатки формы обработки) в таблицу добавляется столбец Остатки, заполняемый процедурой остаткиРасчет общего модуля Гарантия:

процедура остаткиРасчет(тзОтбор) экспорт
 м = тзОтбор.ВыгрузитьКолонку("СН");
 з = новый Запрос;
 з.Текст = "выбрать СерийныйНомер как сн, количествоОстаток как кл
 | из регистрНакопления.ИзделияНаСкладах.Остатки(&дт)
 | где склад = &скл и СерийныйНомер в (&м)";
 з.УстановитьПараметр("дт", конецДня(текущаяДата()));
 з.УстановитьПараметр("скл", константы.СкладПриема.Получить());
 з.УстановитьПараметр("м", м);
 р = з.Выполнить();
 для каждого с из тзОтбор цикл с.Остаток = 0 конецЦикла;
 если не р.Пустой() тогда
  в = р.Выбрать();
  пока в.Следующий() цикл
   с = тзОтбор.Найти(в.сн, "СН");
   с.остаток = в.кл;
  конецЦикла;
 конецЕсли;
конецПроцедуры

Если поиск в базе Гарантия не дал результата, то поиск продолжается в хранилище СН при помощи функции получитьСЗ общего модуля вСН этого хранилища (в свойствах модуля установлен флажок Внешнее соединение).
Дальнейшая обработка полученного списка значений не отличается от обработки списка значений, сформированного по результатам отбора в базе Гарантия.
Заметим, что поиск завершится неудачно, если число отобранных значений слишком велико.

ОБРАБОТКА ОТБОРА ПО ЧАСТИ СН

Форма обработки ОтборПоЧастиСН (рис. 21) открывается после нажатия на кнопку чСН формы документа приема изделий.

Обработка отбора серийных номеров по части серийного номера

Рис. 21. Форма обработки отбора по части СН

При сброшенном флажке Из хранилища СН поиск выполняется в базе Гарантия, в противном случае - в хранилище СН.
Открытие обработки и последующее пополнение табличной части Изделия документа приема изделий обеспечивает следующий, находящийся в форме документа код:

процедура команднаяПанельИзделияЧСН(кнопка)
 стандартнаяОбработка = ложь;
 фрм = обработки.ОтборПоЧастиСН.ПолучитьФорму();
 фрм.ИзменятьСпособОтображенияОкна = изменениеСпособаОтображенияОкна.Разрешить;
 фрм.бкт = этотОбъект;
 кл = изделия.Количество();
 фрм.ОткрытьМодально();
 если изделия.Количество() = кл + 1 тогда
  эф = элементыФормы.изделия;
  эф.ТекущаяСтрока = изделия[кл];
  эф.ЗакончитьРедактированиеСтроки(ложь);
  определитьКнт(изделия[кл]);
 конецЕсли;
конецПроцедуры

Процедура определитьКнт заполняет при необходимости реквизит Клиент документа:

процедура определитьКнт(твр)
 если значениеЗаполнено(твр)тогда
  снС = твр.СерийныйНомер;
  если клиент.Пустая() и не снС.Пустая() и не снС.Покупатель.Пустая() тогда
   клиент = снС.Покупатель;
  конецЕсли;
 конецЕсли;
конецПроцедуры

Как видно из кода, обработка принимает в качестве параметра документ ПриемИзделий (объект). Переменная бкт, хранящая этот параметр, объявлена в модуле обработки с атрибутом Экспорт:

перем бкт экспорт;

Иного кода модуль обработки не содержит.
В обработке после нажатия на кнопку Отобрать в случае удачи заполняется табличная часть и выводится информационная строка с указанием числа отобранных СН и времени поиска, если оно превышает 1 с.
После выбора подходящей строки обработка пополняет табличную часть Изделия редактируемого документа. Если пополнение выполняется из хранилища СН, то в справочники базы Гарантия добавляются отсутствующие в них сведения об изделии, контрагентах и СН.
Далее приводится код модуля формы обработки:

перем эфтп, снСП, сзСН;

процедура добавитьВТвр()
 если тзОтбор.Количество() > 0 тогда
  если вБД тогда
   индекс = тзОтбор.Индекс(эфтп.ТекущаяСтрока);
   снВС = сзСН.получить(индекс).значение;
   сн = сокрП(эфтп.ТекущаяСтрока.сн);
   снС = гарантия.добавитьИзВБ(сн, снВС, снСП, , истина) // проверять = истина
  иначе
   эфтпД = эфтп.текущиеДанные;
   снС = эфтпД.сн;
  конецЕсли;
  с = бкт.изделия.Добавить();
  с.Номенклатура = снС.владелец;
  с.СерийныйНомер = снС;
  с.Количество = 1;
  цн = снС.Цена;
  с.Цена = ?(цн = 0, 1.0, цн);
  этаФорма.Закрыть();
 конецЕсли;
конецПроцедуры

процедура кнопкаВыполнитьНажатие(кнопка)
 добавитьВТвр()
конецПроцедуры

функция выборСН(кд)
 т = "выбрать ссылка как СН,
 | справочник.СерийныеНомера.владелец.артикул как Артикул,
 | справочник.СерийныеНомера.владелец как Изделие, датаРеализации как Дата,
 | покупатель.наименование как Покупатель, гарантия, цена, цена как Остаток
 | из справочник.СерийныеНомера
 | где не пометкаУдаления и код подобно &кд";
 з = новый запрос;
 з.текст = т;
 з.УстановитьПараметр("кд", "%" + кд + "%");
 возврат з.Выполнить();
конецФункции

процедура кнопкаОтоборНажатие(элемент)
 если пустаяСтрока(чСН) тогда
  предупреждение("Укажите строку отбора");
  текущийЭлемент = элементыФормы.чСН;
  возврат
 конецЕсли;
 кд = сокрЛП(чСН);
 если стрДлина(кд) < 3 тогда
  предупреждение("Недостаточная длина строки отбора");
  текущийЭлемент = элементыФормы.чСН;
  возврат
 конецЕсли;
 т = текущаяДата();
 р = ?(вБД, глВнешнееСоединение.вСН.выборСН(кд), выборСН(кд));
 если р.Пустой() тогда
  предупреждение("Пусто")
 иначе
  если вБД тогда
   сзСН = новый списокЗначений;
   тзОтбор = гарантия.создатьТЗОтбор(вБД);
   в = р.выбрать();
   пока в.следующий() цикл
    с2 = в.сн;
    сТ = тзОтбор.Добавить();
    с2Кд = с2.код;
    сзСН.Добавить(с2, с2Кд);
    сТ.СН = с2Кд;
    влд = с2.владелец;
    сТ.артикул = влд.артикул;
    сТ.изделие = влд.Наименование;
    сТ.Дата = формат(с2.ДатаРеализации, глФД);
    сТ.Покупатель = с2.Покупатель.Наименование;
    сТ.Гарантия = с2.Гарантия;
    сТ.Цена = с2.Цена;
   конецЦикла;
  иначе
   тзОтбор = р.Выгрузить();
  конецЕсли;
  тзОтбор.свернуть("СН, Артикул, Изделие, Дата, Покупатель, Цена, Гарантия", "Остаток");
  тзОтбор.сортировать("СН");
  если вБД тогда
   сзСН.СортироватьПоПредставлению();
  иначе
   гарантия.остаткиРасчет(тзОтбор)
  конецЕсли;
  эфтп.СоздатьКолонки();
  для к = 0 по тзОтбор.колонки.количество() - 1 цикл эфтп.Колонки[к].ТолькоПросмотр = истина конецЦикла;
  эфтп.колонки["Остаток"].Видимость = остатки;
  т = текущаяДата() - т;
  кл = тзОтбор.количество();
  если кл > 5 тогда
   т = ?(т > 1, "t = " + т + " с", "");
   кл = "Всего: " + кл + ". " + т;
  иначе
   кл = "";
  конецЕсли; 
  элементыФормы.НадписьОтобрано.Заголовок = кл;
 конецЕсли;
конецПроцедуры

процедура тпВыбор(Элемент, выбраннаяСтрока, Колонка, СтандартнаяОбработка)
 добавитьВТвр()
конецПроцедуры

процедура вБДПриИзменении(элемент)
 эфо = элементыФормы.остатки;
 если тзОтбор.Количество() > 0 тогда
  если вопрос("Таблица будет очищена. Продолжить?", режимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.нет тогда
   вБД = не вБД;
   возврат
  конецЕсли;
  тзОтбор.Очистить();
  если вБД тогда
   эфо.значение = ложь;
   эфтп.колонки["Остаток"].Видимость = ложь;
  конецЕсли;
 конецЕсли;
 эфо.доступность = не вБД;
 текущийЭлемент = элементыФормы.чСН;
конецПроцедуры

процедура остаткиПриИзменении(элемент)
 эфтп.колонки["Остаток"].Видимость = остатки;
конецПроцедуры

эфтп = элементыФормы.тп;
снСП = справочники.СерийныеНомера.ПустаяСсылка();

ОБРАБОТКА ВВОДА ОПИСАНИЯ ИЗДЕЛИЯ

Часть реквизитов принимаемого изделия, такие, как Заявленный дефект, Комментарий, Номер партии, Код, SKU и имя файла с изображением изделия вводятся обработкой ВводОписанияИзделия (рис. 22).

Обработка ввода описания изделия

Рис. 22. Форма обработки ввода описания изделия

Обработка открывается при нажатии на кнопку Описание формы документа приема изделий или после нажатия на кнопку открытия в столбце Описание табличной части документа.
Обработка принимает в качестве параметра структуру, формируемую в модуле формы документа приема изделий:

процедура изделияОписаниеОткрытие(элемент, стандартнаяОбработка)
 стандартнаяОбработка = ложь;
 с = элементыФормы.изделия.ТекущиеДанные;
 если с = неопределено тогда возврат конецЕсли;
 прмтр = новый структура();
 прмтр.Вставить("ДокументОбъект", этотОбъект);
 прмтр.Вставить("НомерСтрокиТабличнойЧасти", с.НомерСтроки);
 прмтр.Вставить("СтрокаТабличнойЧасти", с);
 прмтр.Вставить("Номенклатура", с.Номенклатура);
 прмтр.Вставить("ЗаявленныйДефект", с.ЗаявленныйДефект);
 прмтр.Вставить("Комментарий", с.Комментарий);
 прмтр.Вставить("НомерПартии", с.НомерПартии);
 прмтр.Вставить("Код", с.Код);
 прмтр.Вставить("SKU", с.SKU);
 прмтр.Вставить("Картинка", с.Картинка);
 фрм = обработки.ВводОписанияИзделия.ПолучитьФорму();
 фрм.сИП = прмтр;
 фрм.Открыть();
конецПроцедуры

Параметр сИП модуля обработки объявлен с атрибутом Экспорт.

перем сИП экспорт;

Иного кода в модуле обработки нет. Реквизиты обработки показаны на рис. 23.

Обработка ввода описания изделия: реквизиты

Рис. 23. Реквизиты обработки ввода описания изделия

Тип реквизита Документ - ДокументОбъект.ПриемИзделий, реквизита Номенклатура - СправочникСсылка.Номенклатура. Реквизит НомерСтрокиТабличнойЧасти - числовой, прочие реквизиты - это строки.
Воспроизведение имеющегося описания изделия и сохранение свежих данных обеспечивает код модуля формы обработки:

перем мСтрокаТабличнойЧасти;

функция нчлРбт()
 сИП.Свойство("НомерСтрокиТабличнойЧасти", НомерСтрокиТабличнойЧасти);
 если номерСтрокиТабличнойЧасти = 0 тогда возврат истина конецЕсли;
 сИП.Свойство("Номенклатура", Номенклатура);
 если не значениеЗаполнено(Номенклатура) тогда предупреждение("Не выбрана номенклатура!"); возврат истина конецЕсли;
 сИП.Свойство("ДокументОбъект", Документ);
 сИП.Свойство("СтрокаТабличнойЧасти", мСтрокаТабличнойЧасти);
 сИП.Свойство("ЗаявленныйДефект", ЗаявленныйДефект);
 сИП.Свойство("Комментарий", Комментарий);
 сИП.Свойство("НомерПартии", НомерПартии);
 сИП.Свойство("Код", Код);
 сИП.Свойство("SKU", SKU);
 сИП.Свойство("Картинка", Картинка);
конецФункции

процедура записатьОписаниеВДокумент()
 если документ.Изделия.Индекс(мСтрокаТабличнойЧасти) = -1 тогда возврат; конецЕсли;
 дМИ = документ.Метаданные().Имя;
 мСтрокаТабличнойЧасти.ЗаявленныйДефект = заявленныйДефект;
 мСтрокаТабличнойЧасти.Комментарий = комментарий;
 мСтрокаТабличнойЧасти.НомерПартии = номерПартии;
 мСтрокаТабличнойЧасти.Код = код;
 мСтрокаТабличнойЧасти.SKU = SKU;
 мСтрокаТабличнойЧасти.Картинка = картинка;
 мСтрокаТабличнойЧасти.Смотреть = ?(пустаяСтрока(ЗаявленныйДефект) и пустаяСтрока(Комментарий) и пустаяСтрока(НомерПартии) и пустаяСтрока(Код) и пустаяСтрока(SKU) и пустаяСтрока(Картинка), "Не задано", "Смотреть");
конецПроцедуры

функция проверитьНаМ()
 если этаФорма.Модифицированность тогда
  ответ = вопрос("Сохранить изменения?", РежимДиалогаВопрос.ДаНетОтмена);
  если ответ = кодВозвратаДиалога.Да тогда
   записатьОписаниеВДокумент();
  иначеЕсли ответ = кодВозвратаДиалога.Отмена тогда
   возврат ложь;
  конецЕсли;
 конецЕсли;
 возврат истина;
конецФункции

процедура приПовторномОткрытии(стандартнаяОбработка)
 если проверитьНаМ() тогда
  этаФорма.Модифицированность = ложь;
  нчлРбт();
 конецЕсли;
конецПроцедуры

процедура передЗакрытием(отказ, стандартнаяОбработка)
 отказ = не проверитьНаМ();
конецПроцедуры

процедура кнопкаОКНажатие(кнопка)
 записатьОписаниеВДокумент();
 этаФорма.Модифицированность = Ложь;
 закрыть();
конецПроцедуры

процедура передОткрытием(отказ, стандартнаяОбработка)
 отказ = нчлРбт();
конецПроцедуры

процедура выбратьФайл(элемент, стандартнаяОбработка)
 нДиалог = новый диалогВыбораФайла(режимДиалогаВыбораФайла.Открытие);
 нДиалог.Фильтр = "Файл картинки (*.*)|*.*";
 нДиалог.Заголовок = "Выбор файла картинки";
 если нДиалог.Выбрать() тогда картинка = нДиалог.ПолноеИмяФайла; конецЕсли;
конецПроцедуры

процедура заявленныйДефектНачалоВыбора(элемент, стандартнаяОбработка)
 фрм = справочники.Дефекты.ПолучитьФормуВыбора();
 фрм.ВладелецФормы = этаФорма;
 фрм.ЗакрыватьПриВыборе = ложь;
 фрм.Открыть();
конецПроцедуры

процедура обработкаВыбора(значениеВыбора, источник)
 заявленныйДефект = сокрЛП(заявленныйДефект) + "; " + сокрЛП(значениеВыбора);
 если лев(заявленныйДефект, 1) = ";" тогда заявленныйДефект = сокрЛ(сред(заявленныйДефект, 2)) конецЕсли;
конецПроцедуры

ОТЧЕТ СКЛАДЫ

Показывает остатки изделий на складах организации (рис. 24).

Пример отчета по остаткам изделий

Рис. 24. Отчет по остаткам изделий

В форме отчета (рис. 25) можно задать отборы по складу, производителю и изделию.

Форма отчета Склады: задание отборов

Рис. 25. Форма отчета Склады

Извлечение и вывод результата обеспечивает следующий код модуля отчета:

процедура остаткиНСкл(дт, скл, кнт, твр) экспорт
 н = 0;
 клВ = 0;
 дт2 = конецДня(дт);
 тД = новый табличныйДокумент;
 мкт = получитьМакет("мкт");
 блСкл = мкт.ПолучитьОбласть("скл");
 блРдтл = мкт.ПолучитьОбласть("рдтл");
 бл = мкт.ПолучитьОбласть("зг");
 бл.Параметры.Дт = формат(дт, глФД);
 тД.Вывести(бл);
 тбр = "";
 пСкл = скл.Пустая();
 если не пСкл тогда тбр = тбр + "; " + скл конецЕсли;
 если не кнт.Пустая() тогда тбр = тбр + "; " + кнт конецЕсли;
 если не твр.Пустая() тогда тбр = тбр + "; " + твр конецЕсли;
 если не пустаяСтрока(тбр) тогда
  бл = мкт.ПолучитьОбласть("тбр");
  бл.Параметры.Тбр = сред(тбр, 3);
  тД.Вывести(бл);
 конецЕсли;
 бл = мкт.ПолучитьОбласть("зг2");
 тД.Вывести(бл);
 бл = мкт.ПолучитьОбласть("дтл");
 блП = бл.Параметры;
 блВс = мкт.ПолучитьОбласть("вс");
 блВсП = блВс.Параметры;
 т = "выбрать склад, номенклатура, номенклатура.артикул как рткл, номенклатура.родитель как родитель, номенклатура.основнойПоставщик как производитель,
 | серийныйНомер как сн, количествоОстаток как кл
 | из регистрНакопления.ИзделияНаСкладах.Остатки(&дт2)";
 дб = ?(скл.Пустая(), "", " где склад = &скл");
 дб = дб + ?(кнт.Пустая(), "", ?(пустаяСтрока(дб), " где", " и") + " номенклатура.основнойПоставщик = &кнт");
 дб = дб + ?(твр.Пустая(), "", ?(пустаяСтрока(дб), " где", " и") + " номенклатура = &твр");
 т = т + дб + " упорядочить по склад, номенклатура.Родитель, номенклатура.ОсновнойПоставщик, номенклатура.артикул";
 з = новый Запрос;
 з.Текст = т;
 з.УстановитьПараметр("дт2", дт2);
 если не пСкл тогда з.УстановитьПараметр("скл", скл); конецЕсли;
 если не кнт.Пустая() тогда з.УстановитьПараметр("кнт", кнт); конецЕсли;
 если не твр.Пустая() тогда з.УстановитьПараметр("твр", твр); конецЕсли;
 р = з.Выполнить();
 если р.Пустой() тогда предупреждение("Пусто"); возврат конецЕсли;
 склТ = справочники.Склады.ПустаяСсылка();
 рдтлТ = справочники.Номенклатура.ПустаяСсылка();
 тСкл = р.Выгрузить();
 тСкл.Свернуть("склад", "кл");
 рв = р.Выбрать();
 клВС = 0;
 пока рв.Следующий() цикл
  вывРдтл = ложь;
  если склТ <> рв.Склад и пСкл тогда
   склТ = рв.Склад;
   с = тСкл.Найти(склТ, "склад");
   блСкл.Параметры.Скл = склТ;
   блСкл.Параметры.клВС = ?(с.кл = 0, "0", с.кл);
   тД.Вывести(блСкл);
   вывРдтл = истина;
  конецЕсли;
  если рдтлТ <> рв.Родитель или вывРдтл тогда
   рдтлТ = рв.родитель;
   блРдтл.Параметры.рдтл = рдтлТ;
   тД.Вывести(блРдтл);
  конецЕсли;
  сн = рв.сн;
  н = н + 1;
  блП.н = н;
  блП.рткл = рв.рткл;
  блП.нмн = рв.Номенклатура;
  блП.прзв = рв.производитель;
  блП.сн = сн;
  кл = рв.кл;
  блП.кл = кл;
  тД.Вывести(бл);
  клВ = клВ + кл;
  клВС = клВС + кл;
 конецЦикла;
 если н = 0 тогда
  предупреждение("Пусто");
 иначе
  блВсП.клВ = клВ;
  тД.Вывести(блВс);
  тД.Защита = истина;
  тД.Показать("Изделия");
 конецЕсли;
конецПроцедуры

Модуль формы отчета содержит следующие две процедуры:

процедура кнопкаВыполнитьНажатие(кнопка)
 остаткиНСкл(дт, скл, кнт, твр);
конецПроцедуры

процедура приОткрытии()
 если дт = глДтНач тогда дт = текущаяДата() конецЕсли;
 очиститьСообщения();
конецПроцедуры

ЗАКЛЮЧЕНИЕ

Объекты рассмотренного примера (справочники, документы, регистры и пр.) не имеют избыточности, поскольку созданы для обслуживания типовых операций гарантийного отдела организации. Также благодаря хранилищу СН и внешнему соедининию, обеспечивающему передачу данных из хранилища в базу Гарантия, существенно снижается размер этой базы и, как следствие, ускоряются процессы поиска и выбора данных.

ИСТОЧНИКИ

  1. Синтаксис-помощник 1С:Предприятие.
  2. Тестовые части приложений СН и Гарантия.
Рейтинг@Mail.ru