Имя: Пароль:
1C
1С v8
Обработка подбор номенклатуры (поиск по любому слову номенклатуры )
,
0 asics
 
03.12.14
15:05
когда делаешь поиск по словам,т.е пишешь слово,то поиск ищет только по первому слову а можно сделать по любому слову из номенклатуры и как это сделать если возможно?! (помогите решить вопрос кто знает.)
1 Asmody
 
03.12.14
15:06

(0) можно. называется "полнотекстовый поиск". на ИТС есть демка.

2 Maniac
 
03.12.14
15:06
МОжно
3 Maniac
 
03.12.14
15:06
(1) самый большой тормоз
4 pessok
 
03.12.14
15:07
да оно из коробки ищет нормально
5 pessok
 
03.12.14
15:07
6 Maniac
 
03.12.14
15:09
7 pessok
 
03.12.14
15:10
маня толкает мегапрайс
8 ДенисЧ
 
03.12.14
15:10
Ctrl-F не предлагать?
9 pessok
 
03.12.14
15:10
(8) нет, надо купить мегапрайс :D
10 Maniac
 
03.12.14
15:10
(7) ну так потому что по поиску у меня вообще лучшее решение. я сам кайфую шопипец
11 ДенисЧ
 
03.12.14
15:11
(9) Можно, я не буду?
12 pessok
 
03.12.14
15:11
(10) твой не ковырял, хотя одним клиентам таки присоветовал купить мегапрайс. очень понравился поиск в чьей-то нетленной "Управление сервисным центром"
13 Maniac
 
03.12.14
15:12
(12) да там ничего сверхестественного нет.
через ПОДОБНО все решается в два пальца.
14 Diman000
 
03.12.14
15:12
Может ОбработкаПолученияДанныхВыбора подойдет.
15 Asmody
 
03.12.14
15:12

(10) Твой "суперпоиск" в 8.3.5 реализуется штатными методами.
Да, и реклама на Мисте платная

16 pessok
 
03.12.14
15:12
(13) ну если бы кто-то не закрывал свои модули, я бы даже посмотрел, вот прям щас :)
17 Maniac
 
03.12.14
15:13
(15) в 1С вообще все штатно можно сделать) встроенным языком.
18 pessok
 
03.12.14
15:13
(0) в общем искаропки по ctrl+f все работает, см. (5)
19 Maniac
 
03.12.14
15:13
(16) дык я пароли на модули открываю.
20 Maniac
 
03.12.14
15:13
(16) а это вообще в открытой части модуля формы.
21 pessok
 
03.12.14
15:14
(19) хы, у этих засранцев, оказывается, есть пароль... ладно, стребуем :)
22 Maniac
 
03.12.14
15:15
Мне почему нравится мое больше чем типовое, у меня нет ни одного участка разработок где бы я решал какую то функцию или процедуру на несколько тысяч код строка как это делает 1С в типовых.
Что надо дни тратить чтобы найти концы.

Там вообещ все на экранный лист простым встроенным языком 1С.
23 wertyu
 
03.12.14
15:15
(6) это не поиск, а отбор
24 Kamas
 
03.12.14
15:16
(0) Запрос где Наименование подобно %валенки%
25 asics
 
03.12.14
15:16
Процедура ВыполнитьПоиск()

    Если мВремяПоследнегоПоиска = ТекущаяДата() Тогда

        // Искать не надо, вероятно после изменения текста в окне поиска пользователь нажал на
        // кнопку открытия.

        Возврат;

    КонецЕсли;

    // Надо добавить шаблон в историю
ЭлементИстории = ЭлементыФормы.ПолеПоиска.СписокВыбора.НайтиПоЗначению(ПолеПоиска);
Если ЭлементИстории = Неопределено Тогда
// Надо добавить
ЭлементыФормы.ПолеПоиска.СписокВыбора.Вставить(0, ПолеПоиска);
Иначе// Надо переместить в начало истории
ИндексЭлементаИстории = ЭлементыФормы.ПолеПоиска.СписокВыбора.Индекс(ЭлементИстории);        ЭлементыФормы.ПолеПоиска.СписокВыбора.Сдвинуть(ЭлементИстории, - ИндексЭлементаИстории);
КонецЕсли;
ШаблонПоиска = СокрЛП(ПолеПоиска);
Если ШаблонПоиска = "" Тогда
Возврат;
КонецЕсли;

// заменим спецсимволы
ШаблонПоиска = СтрЗаменить(ШаблонПоиска, "~", "~~");
ШаблонПоиска = СтрЗаменить(ШаблонПоиска, "%", "~%");
ШаблонПоиска = СтрЗаменить(ШаблонПоиска, "_", "~_");
ШаблонПоиска = СтрЗаменить(ШаблонПоиска, "[", "~[");
ШаблонПоиска = СтрЗаменить(ШаблонПоиска, "-", "~-");
ШаблонПоиска = ШаблонПоиска+"%";
    
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ШаблонПоиска", ШаблонПоиска);

Запрос.Текст = "
|ВЫБРАТЬ ПЕРВЫЕ 51
|    Номенклатура.Код КАК Код,
|    Номенклатура.Артикул КАК Артикул,
|    Номенклатура.Ссылка КАК Номенклатура,
|    ПОДСТРОКА(Номенклатура.НаименованиеПолное, 1, 250) КАК НаименованиеПолное,
|    Номенклатура.Родитель КАК Родитель
|ИЗ
|    Справочник.Номенклатура КАК Номенклатура
|
|ГДЕ
|    Номенклатура." + ЭлементыФормы.СписокВидовПоиска.Значение + " ПОДОБНО &ШаблонПоиска СПЕЦСИМВОЛ ""~""
|    И Номенклатура.ЭтоГруппа = Ложь
|";

ВыбраннаяНоменклатура = Неопределено;
Родитель = Неопределено;
ФормаВыбораПоиска = ПолучитьФорму("ФормаВыбораПоиска", ЭтаФорма);
ФормаВыбораПоиска.ТаблицаНоменклатуры = Запрос.Выполнить().Выгрузить();

ВыбраннаяНоменклатура = Неопределено;
Если ФормаВыбораПоиска.ТаблицаНоменклатуры.Количество() = 0 Тогда
        Предупреждение("Отсутствует номенклатура с заданными критериями поиска!");
        мТекущийЭлементФормы = ЭлементыФормы.ПолеПоиска;
        Возврат;
    ИначеЕсли ФормаВыбораПоиска.ТаблицаНоменклатуры.Количество() = 1 Тогда
        ВыбраннаяНоменклатура = ФормаВыбораПоиска.ТаблицаНоменклатуры[0].Номенклатура;
        Родитель              = ФормаВыбораПоиска.ТаблицаНоменклатуры[0].Родитель;
    Иначе
        Если ФормаВыбораПоиска.ТаблицаНоменклатуры.Количество() = 51 Тогда
            Предупреждение("По заданным критериям поиска найдено более 50 элементов номенклатуры!
                            |Будут показаны первые 50.");
            ФормаВыбораПоиска.ТаблицаНоменклатуры.Удалить(50);
        КонецЕсли;

        СтруктураПараметров = ФормаВыбораПоиска.ОткрытьМодально();

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

        Если ВыбраннаяНоменклатура = Неопределено Тогда
            мТекущийЭлементФормы = ЭлементыФормы.ПолеПоиска;
            Возврат;
        КонецЕсли;
    КонецЕсли;

    СтруктураЗапроса = ЭлементыФормы.СписокВидовПодбора.Значение;
    УстановитьТекущегоРодителя(Родитель);
    ПерезаполнитьТаблицуНоменклатуры(Родитель, СтруктураЗапроса);

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

    мВремяПоследнегоПоиска = ТекущаяДата();

КонецПроцедуры
26 Maniac
 
03.12.14
15:17
(23) гы... поиск и есть отбор
27 wertyu
 
03.12.14
15:18
(26) поиск это поиск, а отбор это отбор, иначе бы они они одинаково назывались
28 Maniac
 
03.12.14
15:18
(25) выкинь.
Это найдет только по одному слову.
29 Maniac
 
03.12.14
15:19
(27) от перемены мест слагаемых сумма не меняется.
Чувак написал про ПОДБОР, а в подборах поиск осуществляет отбор. Мозг не взламывай.
30 mikecool
 
03.12.14
15:20
(6) отрыть новое окно?? Женя, ты же не франь и не фирма 1с, мог бы свои продукты грамотно оформлять
31 eklmn
 
гуру
03.12.14
15:20
(25) хрень, запрос с (24) +1
32 Maniac
 
03.12.14
15:21
Расширим задачу так.

Человек не просто слово задает. А пару слов. Или даже может слогов.

Поиск должен найти номенклатуру в которых эти два слога есть в наименовании в любых частях целых слов.
Но не одновременно в одном из них.

Тоесть человек может задать через пробел 2-3 и тп слов/слогов.
Программа должна отобрать номенклатурву в которой эти 2-3 слога есть в РАЗНЫХ словах искомого наименования.
33 Maniac
 
03.12.14
15:22
(30) старая версия в (6). Просто демонстрация поиска. Я скриншоты редко обновляю.

Новая версия уже выглядит так
http://subsystems.ru/upload/iblock/f5e/rmm_prodaz_1.png
34 wertyu
 
03.12.14
15:23
(32) %частьслова1%|%частьслова2%
35 Maniac
 
03.12.14
15:24
Как я понял автор еще хочет чтобы по разным полям было.
Например даже дополнительное описание.
36 Maniac
 
03.12.14
15:25
иногда некоторые хотят еще и по свойствам.
37 asics
 
03.12.14
15:25
только по номенклатуре (36)
38 RomaH
 
naïve
03.12.14
15:42
полнотекстовый имеет ограничения
он по коротким словам не ищет - пишет про переполнение индекса

у меня что-то на подобии (6) прикручено к поиску контрагентов (но вот насчет одной страницы кода - это правда? - у меня 390 строк + немного из общего модуля)

фраза разбивается на массив слов
потом создается массив фраз ( в "подобно" вроде как порядок имеет значение ) поэтому ограничение на 5 слов во фразе поиска


        Для К = 0 По МассивСтрокПоиска.ВГраница() Цикл
            
            Если ТипЗнч(МассивСтрокПоиска[К]) = Тип("Массив") Тогда
                
                МассивСлов = МассивСтрокПоиска[К];
                
                УсловиеФильтра = "(ИСТИНА";
                
                Для Ш = 0 ПО МассивСлов.ВГраница() Цикл
                    
                    ИП = Формат(Ш,"ЧГ=0");
                    Слово = МассивСлов[Ш];
                    УсловиеФильтра = УсловиеФильтра +
                    "
                    |    И (Контрагенты.Наименование ПОДОБНО &ТекстФильтра" + ИП + "
                    |    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &ТекстФильтра" + ИП + ")";
                    
                    Запрос.УстановитьПараметр("ТекстФильтра" + ИП,"%" + Слово + "%");
                    
                КонецЦикла;
                
                УсловиеФильтра = УсловиеФильтра + ")";
                
                Продолжить;
                
            КонецЕсли;
            
            ИП = Формат(К,"ЧГ=0");
            Запрос.УстановитьПараметр("Текст" + ИП,"" + МассивСтрокПоиска[К] + "");
            
            ТекстУсловия = ТекстУсловия +
            "
            |    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст" + ИП + "
            |    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст" + ИП;
            
        КонецЦикла;
39 RomaH
 
naïve
03.12.14
15:45
в итоге получаю вот такой запрос:

Свойство    Значение    Тип
Запрос    Запрос    Запрос
МенеджерВременныхТаблиц        Неопределено
Параметры    Структура    Структура
ДоговорПрофосмотра        ДокументСсылка.ДоговорНаПроведениеМедОсмотров
КатегорияВнереализации        Неопределено
Текст    "%дор%[^а-я0-9]%бол%[^а-я0-9]%клин%[^а-я0-9]%яр%"    Строка
Текст1    "%дор%[^а-я0-9]%яр%[^а-я0-9]%клин%[^а-я0-9]%бол%"    Строка
Текст10    "%клин%[^а-я0-9]%дор%[^а-я0-9]%яр%[^а-я0-9]%бол%"    Строка
Текст11    "%клин%[^а-я0-9]%бол%[^а-я0-9]%яр%[^а-я0-9]%дор%"    Строка
Текст12    "%бол%[^а-я0-9]%клин%[^а-я0-9]%дор%[^а-я0-9]%яр%"    Строка
Текст13    "%бол%[^а-я0-9]%яр%[^а-я0-9]%дор%[^а-я0-9]%клин%"    Строка
Текст14    "%бол%[^а-я0-9]%дор%[^а-я0-9]%клин%[^а-я0-9]%яр%"    Строка
Текст15    "%бол%[^а-я0-9]%яр%[^а-я0-9]%клин%[^а-я0-9]%дор%"    Строка
Текст16    "%бол%[^а-я0-9]%дор%[^а-я0-9]%яр%[^а-я0-9]%клин%"    Строка
Текст17    "%бол%[^а-я0-9]%клин%[^а-я0-9]%яр%[^а-я0-9]%дор%"    Строка
Текст18    "%яр%[^а-я0-9]%клин%[^а-я0-9]%дор%[^а-я0-9]%бол%"    Строка
Текст19    "%яр%[^а-я0-9]%бол%[^а-я0-9]%дор%[^а-я0-9]%клин%"    Строка
Текст2    "%дор%[^а-я0-9]%клин%[^а-я0-9]%бол%[^а-я0-9]%яр%"    Строка
Текст20    "%яр%[^а-я0-9]%дор%[^а-я0-9]%клин%[^а-я0-9]%бол%"    Строка
Текст21    "%яр%[^а-я0-9]%бол%[^а-я0-9]%клин%[^а-я0-9]%дор%"    Строка
Текст22    "%яр%[^а-я0-9]%дор%[^а-я0-9]%бол%[^а-я0-9]%клин%"    Строка
Текст23    "%яр%[^а-я0-9]%клин%[^а-я0-9]%бол%[^а-я0-9]%дор%"    Строка
Текст3    "%дор%[^а-я0-9]%яр%[^а-я0-9]%бол%[^а-я0-9]%клин%"    Строка
Текст4    "%дор%[^а-я0-9]%клин%[^а-я0-9]%яр%[^а-я0-9]%бол%"    Строка
Текст5    "%дор%[^а-я0-9]%бол%[^а-я0-9]%яр%[^а-я0-9]%клин%"    Строка
Текст6    "%клин%[^а-я0-9]%бол%[^а-я0-9]%дор%[^а-я0-9]%яр%"    Строка
Текст7    "%клин%[^а-я0-9]%яр%[^а-я0-9]%дор%[^а-я0-9]%бол%"    Строка
Текст8    "%клин%[^а-я0-9]%дор%[^а-я0-9]%бол%[^а-я0-9]%яр%"    Строка
Текст9    "%клин%[^а-я0-9]%яр%[^а-я0-9]%бол%[^а-я0-9]%дор%"    Строка
ТекстФильтра    "%дор%"    Строка
ТекстФильтра1    "%клин%"    Строка
ТекстФильтра2    "%бол%"    Строка
ТекстФильтра3    "%яр%"    Строка
Текст    "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    Контрагенты.Ссылка,
    Контрагенты.ПометкаУдаления,
    Контрагенты.Код,
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.НаименованиеПолное КАК НаименованиеПолное,
    Контрагенты.Вес,
    Контрагенты.КоличествоСвязей
ПОМЕСТИТЬ втКонтрагентыФильтр
ИЗ
    Справочник.Контрагенты КАК Контрагенты
        ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
            ДоговорНаПроведениеМедОсмотровСписокМестРаботы.Контрагент КАК Контрагент
        ИЗ
            Документ.ДоговорНаПроведениеМедОсмотров.СписокМестРаботы КАК ДоговорНаПроведениеМедОсмотровСписокМестРаботы
        ГДЕ
            (ДоговорНаПроведениеМедОсмотровСписокМестРаботы.Ссылка = &ДоговорПрофосмотра
                    ИЛИ &ДоговорПрофосмотра = ЗНАЧЕНИЕ(Документ.ДоговорНаПроведениеМедОсмотров.ПустаяСсылка))) КАК КонтрагентыПоДоговору
        ПО (КонтрагентыПоДоговору.Контрагент = Контрагенты.Ссылка
                ИЛИ КонтрагентыПоДоговору.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ЧастноеЛицо))
ГДЕ
    НЕ Контрагенты.НельзяВыбрать
    И ВЫБОР
            КОГДА &КатегорияВнереализации <> ЗНАЧЕНИЕ(Перечисление.КатегорииВнереализации.ПенсионерИнвалидЖД)
                ТОГДА НЕ Контрагенты.ТолькоДляПенсионеров
            ИНАЧЕ ИСТИНА
        КОНЕЦ
    И (НЕ КонтрагентыПоДоговору.Контрагент ЕСТЬ NULL
            ИЛИ &ДоговорПрофосмотра = НЕОПРЕДЕЛЕНО)

;


ВЫБРАТЬ
    Контрагенты.Ссылка,
    Контрагенты.ПометкаУдаления,
    Контрагенты.Код,
    Контрагенты.Наименование КАК Наименование,
    Контрагенты.НаименованиеПолное КАК НаименованиеПолное,
    Контрагенты.Вес,
    Контрагенты.КоличествоСвязей
ПОМЕСТИТЬ втКонтрагенты
ИЗ
    втКонтрагентыФильтр КАК Контрагенты
ГДЕ
    (ИСТИНА
    И (Контрагенты.Наименование ПОДОБНО &ТекстФильтра
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &ТекстФильтра)
    И (Контрагенты.Наименование ПОДОБНО &ТекстФильтра1
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &ТекстФильтра1)
    И (Контрагенты.Наименование ПОДОБНО &ТекстФильтра2
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &ТекстФильтра2)
    И (Контрагенты.Наименование ПОДОБНО &ТекстФильтра3
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &ТекстФильтра3))
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ ПЕРВЫЕ 51
    Контрагенты.Ссылка,
    Контрагенты.ПометкаУдаления,
    Контрагенты.Код,
    Контрагенты.Наименование КАК Наименование
ИЗ
    втКонтрагенты КАК Контрагенты
ГДЕ
    (ЛОЖЬ
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст1
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст1
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст2
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст2
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст3
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст3
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст4
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст4
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст5
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст5
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст6
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст6
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст7
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст7
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст8
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст8
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст9
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст9
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст10
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст10
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст11
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст11
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст12
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст12
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст13
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст13
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст14
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст14
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст15
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст15
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст16
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст16
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст17
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст17
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст18
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст18
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст19
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст19
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст20
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст20
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст21
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст21
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст22
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст22
    ИЛИ Контрагенты.Наименование ПОДОБНО &Текст23
    ИЛИ Контрагенты.НаименованиеПолное ПОДОБНО &Текст23)

УПОРЯДОЧИТЬ ПО
    Контрагенты.Вес УБЫВ,
    Контрагенты.КоличествоСвязей УБЫВ,
    Наименование
;

////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ втКонтрагенты"    Строка
40 Maniac
 
03.12.14
15:49
(38) Практически также
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн