Можно ли закрыть Администратору доступ к определенным записям грида, как обычным Пользователям?

Нравится

3 комментария

Добрый день!

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

Можно конечно и фильтрик какой на грид приделать, чтобы всегда для администратора применялся... тем более в 3ке это не проблема - новый GridView с фильтром и код, чтобы его включал несчастному ограниченному админу. Но это как то идеологически неверно.
Менять надо такого администратора, которому доверия нет :wink:

"Alex GF" написал:Можно ли закрыть Администратору доступ к определенным записям грида, как обычным Пользователям?

надо понимать, что он сможет это дело отключить (теоретически)
"Александр Кудряшов" написал:фильтрик какой на грид приделать

лучше делать фильтр на датасет (чтобы в справочнике тоже не отображалось)

Показать все комментарии

Кто-то знает этот запрос (для чего он, зачем и можно ли оптимизировать):

exec sp_executesql N'SELECT
        [vw_Account].[ID] AS [ID],
        [vw_Account].[Name] AS [Name]
FROM
        [dbo].[vw_Account] AS [vw_Account]
WHERE(EXISTS
        (SELECT
                [vw_Contact].[ID] AS [ID]
        FROM
                [dbo].[vw_Contact] AS [vw_Contact]
        WHERE([vw_Contact].[AccountID] = [vw_Account].[ID] AND
                EXISTS
                (SELECT
                        [tbl_AdminUnit].[ID] AS [ID]
                FROM
                        [dbo].[tbl_AdminUnit] AS [tbl_AdminUnit]
                WHERE([tbl_AdminUnit].[UserContactID] = [vw_Contact].[ID] AND
                        [tbl_AdminUnit].[UserIsEnabled] = @P1)))))
ORDER BY
        2 ASC'
,N'@P1 int',1

Нравится

18 комментариев

Угадайка?

Выбор контрагентов, указанных для активных пользователей системы.
В каком месте хранится искать неохота.

Можно exists убрать и условие ядреное, через inner join как мне кажется... только надо ли?

"Александр Кудряшов" написал:Можно exists убрать

Спасибо, Александр!
К сожалеюнию, пока нельзя убрать, так как не знаю откуда оно формируется. Но когда узнаю, то постараюсь сделать поле "IsUserAccount", в которое запихивать 1 при создании нового юзера с новым юзерКонтрагентом. тада выборка будет проще

SELECT
        [vw_Account].[ID] AS [ID],
        [vw_Account].[Name] AS [Name]
FROM
        [dbo].[vw_Account] AS [vw_Account]
WHERE IsUserAccount IS NOT NULL

Мне кажется отработает раз в 100 быстрее

SELECT
        [vw_Account].[ID] AS [ID],
        [vw_Account].[Name] AS [Name]
FROM
        [dbo].[[tbl_AdminUnit] AS [[tbl_AdminUnit]
inner join [vw_Contact] on [tbl_AdminUnit].[UserContactID] = [vw_Contact].[ID]
inner join [vw_Account] on [vw_Contact].[AccountID] = [vw_Account].[ID]
 
WHERE [tbl_AdminUnit].[UserIsEnabled] = @P1
 
ORDER BY
        2 ASC',N'@P1 int',1

формируется именно из системы, где-то сервис запроса есть, можно его переписать...

а что реально долго работает и тормозит систему???

ps почитал изыскания пытливых умов - вроде как exists в такой ситуации даже быстрее inner'а отработает

затер сообщение. был неправ :lol:

"AlexLS" написал:в которое запихивать 1 при создании нового юзера с новым юзерКонтрагентом

не правильно - надо это поле перезаписывать при изменении признака Активен любого пользователя, привязанного к этому контрагенту и выставлять в 0, если активных пользователей не осталось

"Андросов Дмитрий" написал:не правильно - надо это поле перезаписывать при изменении признака Активен любого пользователя, привязанного к этому контрагенту и выставлять в 0, если активных пользователей не осталось

Дмитрий, спасибо за ответ! Остается малое - выяснить откуда этот зловещий код выполняется!

"Александр Кудряшов" написал:а что реально долго работает и тормозит систему???

к сожалению из "самых страшных" в нашей терре он на 5 месте (остальные прорабатываю), а по частоте выполнения лидирует! То есть суммарный дюрейшен у юзеров зашкаливает!!!

а вообще это похоже на запрос для какого-то справочника типа "Контрагенты ответсвенных"
поищите UserIsEnabled с помощью GREP (у меня есть только в wnd_LicenseManagerScript, но там не то)
вот для сравнения запрос для справочника Ответсвенный (поиск по имени)

exec sp_executesql N'SELECT TOP 2
	[tbl_Contact].[ID] AS [ID],
	[tbl_Contact].[Name] AS [Name]
FROM
	[dbo].[vw_Contact] AS [tbl_Contact]
INNER JOIN
	[dbo].[tbl_AdminUnit] AS [tbl_AdminUnit] ON [tbl_AdminUnit].[UserContactID] = [tbl_Contact].[ID]
WHERE([tbl_AdminUnit].[UserIsEnabled] = @P1 AND
	[tbl_Contact].[Name] LIKE @P2 + ''%'')
ORDER BY
	1 ASC',N'@P1 int,@P2 nvarchar(4000)',1,N'слепо'

"Андросов Дмитрий" написал:но там не то

Я вот тоже не нашел :)
Похожие запросы есть в Users, LicenseManager, но вот точно такого же не было

"Андросов Дмитрий" написал:поищите UserIsEnabled с помощью GREP

к сожалению эта штука ищет только в scr_
а вот в sq_ увы...

"Александр Кудряшов" написал:Похожие запросы есть в Users, LicenseManager, но вот точно такого же не было

хехех. еще бы уметь его находить...

этот запрос выполняется перед function wnd_MainOnPrepare(Window). Как я понимаю, его и ядро юзает...

Выполняется он при старте перед:

exec sp_executesql N'SELECT
	[tbl_SystemSetting].[ID] AS [ID],
	[tbl_SystemSetting].[Code] AS [Code],
	[tbl_SystemSetting].[ValueTypeID] AS [ValueTypeID],
	[tbl_SystemSetting].[StringValue] AS [StringValue],
	[tbl_SystemSetting].[FloatValue] AS [FloatValue],
	[tbl_SystemSetting].[IntegerValue] AS [IntegerValue],
	[tbl_SystemSetting].[BooleanValue] AS [BooleanValue],
	[tbl_SystemSetting].[DateTimeValue] AS [DateTimeValue],
	[tbl_SystemSetting].[DictionaryRecordID] AS [DictionaryRecordID],
	[tbl_SystemSetting].[EnumItemID] AS [EnumItemID],
	[tbl_SystemSetting].[IsCaching] AS [IsCaching]
FROM
	[dbo].[tbl_SystemSetting] AS [tbl_SystemSetting]
WHERE([tbl_SystemSetting].[Code] = @P1)',N'@P1 nvarchar(4000)',N'UpdateActiveSessionPeriod'

Так это... раз уж во все тяжкие (с)
Дебаггер в scr_Main и по шагам идем, ждем появления в профайлере заветных строчек

"Александр Кудряшов" написал:

Так это... раз уж во все тяжкие (с)

Дебаггер в scr_Main и по шагам идем, ждем появления в профайлере заветных строчек


Александр, а есть код выполняющийся перед wnd_MainOnPrepare?

"AlexLS" написал:а есть код выполняющийся перед wnd_MainOnPrepare?

Это уже пограничная область знаний, тут То Самое Ядро может что-то вызывать. Это за пределами моих знаний:smile:
Там раньше окно авторизации и проверка лицензии как раз идет, окно авторизации вроде бы в конфигурации от греха подальше спрятали

"Александр Кудряшов" написал:Там раньше окно авторизации и проверка лицензии как раз идет

она и есть, наверняка, проверка лицензии... Где еще может понадобиться контрагент пользователя? А значит ничего с этим не сделаете. Вам стоит по этому вопросу обращаться напрямую в тех поддержку, причем желательно сразу на кого-нибудь из старожилов с третьей линии выходить :wink: Но, как правило, по всем вопросам, связанным с лицензиями все заканчивается заявлением, что механизм лицензирования закрыт и сакрален :lol:

"Александр Кудряшов" написал:тут То Самое Ядро может что-то вызывать

Александр, вот мне кажется что ядро вызывает банальный sq_ который и поправили под собственные нужды не задумываясь, что оно где-то глобально юзается!!!

Кстати, оно же (запрос) вызывается и Outlook'ом...

"Андросов Дмитрий" написал:по всем вопросам, связанным с лицензиями все заканчивается заявлением, что механизм лицензирования закрыт и сакрален

Дмитрий, мне кажется что лицензии врядли вьюхой проверять будут, скорее всего обращались бы напрямую к tbl_Account и, так же кажется, что разработчики Террасофта, все-таки не настолько ... (тут каждый сам себе додумает), чтобы такой идиотский код. Хотя, возможно, и у них есть отдельные личности, к примеру разработчики лицензирования :smile:
В принципе, в недалекой перспективе, предполагаем переход на TSv7 и эта тайна может так и остаться не разрешенной, хотя кто знает, может на смену мне прийдут новые :biggrin: с этим же вопросом!

Кстати, очередной банальный (уж простите) вопрос: если выгрузить все сервисы в файлы и потом какой-нить утилиткой "поиск текста в xml" пройтись, тогда шансы на поиск увеличатся?

"AlexLS" написал:чтобы такой идиотский код

Ход абсолютно верен.
У простых пользователей НЕТ доступа к tbl_Account, а есть доступ только к vw_Account.
И проверка лицензии не то, ради чего стоит ломать имеющийся движок обращения к данным.

"Александр Кудряшов" написал:И проверка лицензии не то, ради чего стоит ломать имеющийся движок обращения к данным.

Да, может и так... поискал в sq_ по слову "UserIsEnabled" нашлось в sq_AdminUnit, sq_Contact, sq_ContactInTask, sq_User

Судя по Grep-поиску в скриптах и нахождению етого слова в wnd_LicenseManagerScript ... закрываю тему, благо ясно что этот код зашит

Показать все комментарии

И снова здравствуйте!

Третий день мучаюсь с экспортом контрагентов в 1C. Сам контрагент, включая название передаётся легко, но загвоздка в его деталях - адресах, ИНН и КПП.

Адреса берутся из набора данных ТС "Адреса контрагента", а ИНН и КПП - из "Платежные реквизиты" но экспортируются в самого контрагента. То есть, это, вроде, подчинённые детали, а вроде и нет.

Сейчас детали настроены как подчинённые, чтобы была связь с самим контрагентом. Скорее всего, нужно правильное ключевое поле, которое я не могу подобрать. Всякие ID не будут совпадать, т.к. разные объекты в Террасофт, а других зацепок, по сути, нет.

Кто-нибудь решал эту проблему?

Нравится

14 комментариев

С ИНН и КПП разобрался программно, а также с произвольной строкой адреса. Теперь осталось только передавать детали адреса - Страну, Город, Улицу и т.д.

Лично у меня экспорт контрагентов всё одной настройкой...
Вот кусок с адресами. Событие OnAfterRecordExport:

//удалить  все адреса и средства связи	
	var ci1C = Param.Obj1C.РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей(); 
	ci1C.Отбор.Объект.Установить(Select1C.Ссылка);
	//[не регистрируем изменения на стороне 1с	
	ci1C.ОбменДанными.Получатели.АвтоЗаполнение = false;
	//]
	ci1C.Записать(); 	
	//Адреса
	var AccountID = Dataset('ID');	
	var ds = Services.GetNewItemByUSI('ds_AccountAddress');
	ApplyDatasetFilter(ds, 'AccountID', AccountID, true);
	ds.Open();
	while(!ds.IsEOF) {
		var ci1CMain = Param.Obj1C.РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей();
		var ci1C = ci1CMain.Добавить();
		ci1C.Объект = Select1C.Ссылка;
		var met=Param.Obj1C.Метаданные.Перечисления.Найти("ТипыКонтактнойИнформации");
		var meta=met.ЗначенияПеречисления.Найти('Адрес');
		var metalink = Param.Obj1C.Перечисления.ТипыКонтактнойИнформации[meta.Имя];
		ci1C.Тип = metalink;
		var AdrTypeID = ds('KLADRAddressTypeID');
		var AdrTypeUID1C = GetDatasetFieldValueByID('ds_AddressType',
			AdrTypeID, 'UID1C');
		var AddressType1CLink;
		if(!IsEmptyValue(AdrTypeUID1C)) {
			AddressType1CLink = GetObjectLinkByUID(
					Param.Obj1C.Справочники.ВидыКонтактнойИнформации, AdrTypeUID1C, Param);	
			ci1C.Вид = !AddressType1CLink.Пустая() ? AddressType1CLink : null;
			ci1C.Представление = ds('KLADRAddress');
			ci1C.Поле1 = ds('KLADRAddressZIP');
			ci1C.Поле2 = ds('KLADRAddressSubject');
			ci1C.Поле3 = ds('KLADRAddressRegion');
			ci1C.Поле4 = ds('KLADRAddressDistrictCenter');
			ci1C.Поле5 = ds('KLADRAddressCity');
			ci1C.Поле6 = ds('KLADRAddressStreet');
			ci1C.Поле7 = ds('KLADRAddressHouse');
			ci1C.Поле8 = ds('KLADRAddressCase');
			ci1C.Поле9 = ds('KLADRAddressFlat');
			//[не регистрируем изменения на стороне 1с	
			ci1CMain.ОбменДанными.Получатели.АвтоЗаполнение = false;
			//]						
			ci1CMain.Записать(false); 
		}		
		ds.GotoNext();
	}
	ds.Close();

По поводу заполнения справочных реквизитов...
Получаете ID страны из детали адреса, далее по этому ID получаете значение в поле UID1C, и далее получаете ссылку на страну в 1с, и кладете её в реквизит...
Примерно так:

var Invoice1C = Param.Obj1C.Документы.Счет;
var InvoiceUID1C = GetDatasetFieldValueByID('ds_Opportunity', 
	dlData.Dataset('ID'), 'UID1C');
InvoiceUID1C = CreateGUID1C(InvoiceUID1C, Param.Obj1C);
var Link1C = Invoice1C.GetRef(InvoiceUID1C);
function CreateGUID1C(UID1C, Obj1C) {
	if(UID1C == null) {
		return '';
	}
	UID1C = UID1C.replace('{', '');
	UID1C = UID1C.replace('}', '');
	UID1C = Obj1C.NewObject('УникальныйИдентификатор', UID1C);
	return UID1C;
}

> Лично у меня экспорт контрагентов всё одной настройкой...

Да, этот ваш код мне сильно помог, хоть он и не подходит для 1С 8.3, так как "РегистрыСведений.КонтактнаяИнформация" больше не существует, они переехали в справочники.

> Получаете ID страны из детали адреса, далее по этому ID получаете значение в поле UID1C, и далее получаете ссылку на страну в 1с, и кладете её в реквизит...

Интересно. Меня смутило, что механизм интеграции определил эти поля как простые Строки, но попробовать надо.

ОК. Если что будет конкретного: кидайте ваш код или скрины.

Попробовал, не то чтобы получилось. Работает всё так:

Берём объект:

var Contragent = Select1C.Ссылка.ПолучитьОбъект();

Получаем его ID, идём по списку адресов, добавляя каждый:

var AccountID = Dataset('ID');
 
var ds = Services.GetNewItemByUSI('ds_AccountAddress');
ApplyDatasetFilter(ds, 'AccountID', AccountID, true);
ds.Open();
 
while(!ds.IsEOF) {
      AddAddress(Param, Contragent, ds);
      ds.GotoNext();
}
ds.Close();

Функция AddAddress:

	var newAddress= Contragent.КонтактнаяИнформация.Добавить() ;
	newAddress.Тип = Param.Obj1C.Перечисления.ТипыКонтактнойИнформации.Адрес;
 
	switch(Dataset('AddressTypeID'))
	{
		//Добавляем вид адреса
	}
 
       //Из комментария выше
	var Contragent1C = Param.Obj1C.Справочники.СтраныМира;
	var CountryUID1C = GetDatasetFieldValueByID('ds_Country', Dataset('CountryID'), 'UID1C');
	CountryUID1C = CreateGUID1C(CountryUID1C, Param.Obj1C);
	newAddress.Страна = Contragent1C.GetRef(CountryUID1C); 
 
	Contragent.Записать(false);

При этом поле Страна отображается верно. Однако, при обзоре в клиенте 1С, поле не заполнено.

Как-то так пока.

После записи выполните запрос в 1с и посмотрите что в этом поле. Если ничего - значит не записалось. Возможно срабатывают какие то проверки "перед записью" на стороне 1с?

Имеется ввиду запрос к БД 1С? Я, честно говоря, не в курсе, как это сделать с файловой версией 1С.

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

Посмотрите в 1С Администраторе - быть может в коде формы есть какая-то логика...

В функции РазместитьКонтактнуюИнформацию() логика загрузки простая:

ТаблицаРазмещенияКИ	= УправлениеКонтактнойИнформациейБП.ПолучитьПустуюТаблицуРазмещенияКонтактнойИнформации();
 
УправлениеКонтактнойИнформациейБП.ДобавитьОписаниеРазмещенияКонтактнойИнформации(ТаблицаРазмещенияКИ, Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента, Элементы.ЮрАдресКонтрагента.ПутьКДанным);

Ничего подозрительного пока не заметил.

Ну смотрите, предлагаю сделать так: зайдите в 1с и в меню "Операции" выберите "Обработка". Найдите там "КОнсоль запросов" либо "Консоль отчетов" (если нет - установите), и после записи через ТС выполните в обработке запрос к БД (думаю для файловой БД они тоже работают):

Выбрать ВашРеквизит Из Справочник.ВашСправочник.ВашаТаблЧасть
Где Ссылка.Наименование = "МойКонтрагент"

Если реквизит будет заполнен - значит запись проходит, если нет - значит нет :)

Если проходит - смотрите логику на карточке или в модуле объекта (чтото его при открытии чистит).
Если не проходит (но устанавливает корректно) - значит смотрите события модуля ПередЗаписью - что-то там его чистит.
Если не проходит (и не устанавливается) - скорее всего попутаны типы данных для реквизита.

пс: выполнение 1с-ного кода через COM (Террасофт) также можно отлаживать - погуглите.

Та-да! Всё дело в поле "ЗначенияПолей" (sic!), которое содержит... значения полей! То есть, значения всех остальных полей, у которых есть и свои собственные значения, только в xml формате. Я уже попробовал просто вбить скопированный и подправленный xml, всё загружается. Подробнее инфу можно найти тут: http://forum.aeroion.ru/topic779.html

Спасибо, Дмитрий. Без консоли запросов я бы ещё долго бился бы об это.

Ого! Это что-то новое :)

Показать все комментарии

Настроил возможность открывать файл в гриде
Для события OnLookupColumnClick grdData нужного грида сделал:

function grdDataOnLookupColumnClick(DataGrid, DataGridColumn, Shift) {  debugger;
        var Dataset = dlData.Dataset;
        Dataset.DisableEvents();
        try {
                Record = GetDatasetFieldValue(Dataset, 'Record');
                var wsh = new ActiveXObject("WScript.Shell");
                wsh.Run(Record, 0, false);
        } catch(error) {
                ShowWarningDialog(error.name + ": " + error.message);
        } finally {
                Dataset.EnableEvents();
        }
}

для колонки colRecord установил свойство LookupType в dgcltLookup.

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

Нравится

10 комментариев

Так надо посмотреть что там в случае Записи или Клиента в параметре DataGridColumn передается, и по условию ваш код применять

один обработчик для клика по всем lookup-колонкам

"Андросов Дмитрий" написал:один обработчик для клика по всем lookup-колонкам

Так можно же

if (DataGridColumn.Name == 'colRecord')

а если не выполняется, вызывать родительский

scr_BaseGridArea.grdDataOnLookupColumnClick(DataGrid, DataGridColumn, Shift);

Да, так и сделал.

"Александр Кудряшов" написал:Так можно же

но обработчик-то один :wink:

"Андросов Дмитрий" написал:но обработчик-то один

Да оно понятно, что один :wink:
Главное параметр работает в вызове, мог же и не срабатывать :redface:

Идея понравилась, решила использовать.
Но у меня при открытии ссылки выдается просто окно "Error:"
Это происходит только при нажатии на новую созданную колонку.
Я создавала строковое поле, и заполняла его так: \\server\папка\имя_файла.jpeg
Доступ к этому ресурсу в сети у меня есть.

"Тихенко Виктория" написал:\\server\папка\имя_файла.jpeg

Тут скорее всего должны быть заменены одинарные слэши двойными везде...

Поменяла на двойные, не помогло. Так же выскакивает "Error:"

Можно попробовать в консоли посмотреть, что же там происходит и куда идет обращение

Показать все комментарии

Общая картина:
Есть настроена интеграция, импорт/экспорт
деталь адресса только импорт, экспорт делается через скрипт. Все бы хорошо, записывает в 1С адреса, но поле Code1C пустое и при импорте создается новая запись.
вот часть кода где записывается адресс в 1С:

 var ci1CMain = Param.Obj1C.РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей();
 var ci1C = ci1CMain.Добавить();
 ci1C.Объект = Select1C.Ссылка;
 ci1C.Тип = metalink;
 ci1C.Вид = !AddressType1CLink.Пустая() ? AddressType1CLink : null;
 ci1CMain.Записать(false);  

пример значения поля:"f90039f8-ce1b-11e4-849f-002590a73b07#//#Адрес#//#87d961a6-9e2f-405c-855e-215869755d34#//#"
первую часть(f90039f8-ce1b-11e4-849f-002590a73b07) я могу получить так: Param.Obj1C.XMLString(Select1C.Ref.UUID()).
а как и где получить это:"87d961a6-9e2f-405c-855e-215869755d34"???

Нравится

2 комментария

Спасибо за Ваше обращение. Мы зарегистрировали его в Службе технической поддержки и назначили специалиста, который сможет Вас компетентно проконсультировать по данному вопросу.

К сожалению - это регистр сведений и в нем нет никакого UID который определит уникальность. Добавьте поле "Значение" и "Тип средства связи" как ключевое, либо перед имопртом очищайте деталь, и загружайте все средства связи по объекту.

Показать все комментарии

Добрый день, коллеги.
Такой вопрос: в случае ошибки в приложении Terrasoft выскакивает окошко "Terrasoft CRM - Ошибка приложения". В этом окошке есть кнопка "Послать отчет". Мне интересно, как это работает (SMTP, FTP, IMAP или какой-то ваш Web-сервис) и можно ли настроить таким образом, чтобы наши разработчики тоже могли получать эти отчеты об ошибках?

Нравится

2 комментария

Здравствуйте!

Сам Terrasoft не отправляет почту, для этого используется интеграция с Outlook, который выступает в роли почтового клиента. Касательно вопроса настройки отправки отчетов об ошибке на почтовый ящик разработчика, то данный вопрос уже обсуждался в этом топке.

Приятного дня!

Спасибо.

Показать все комментарии

В sq_ сервисе есть возможность установить свойство "Использовать представление без фильтра по правам" (на скриншоте). Но это свойство неактивно. Как сделать его активным?

С помощью этого свойства хотел проверить возможность в sq_ запросе выводить записи по которым для пользователей нет доступа (к примеру в гриде нет доступа (деталь Доступ), но с помощью sq_ запроса выводим записи, к которым в гриде доступ запрещен). Можно ли это реализовать с помощью этого свойства или как-то по другому?

Нравится

3 комментария

сначала поставьте галочку в целевой таблице
**как работает не знаю)

Попробовал этот функционал с установкой этой галки - не совсем подошел, т.к. в других местах посыпались ошибки.
Возможно ли это сделать другими средствами?

Т.е. есть определенный sq_запрос
С помощью фильтра вывожу Конрагентов:

        var selectQuery = GetSingleItemByCode('sq_Search');
	ApplySelectQueryFilter(selectQuery, 'ID', AccountID, true);
	var dataset = selectQuery.Open();

У Администраторов все выводится как надо, но для обычных пользователей не выводятся Контрагенты к которым у них нет доступа (отсутствуют Группа или сам пользователь в Детали Доступ грида Контрагенты). И этих контрагентов в данном запросе-фильтре нужно показать для обычных пользователей.
Судя по профайлеру в sq_запросе sq_Search для обычных пользователей вместо tbl_Account выводится vw_Account. А для vw_ уже применяются права доступа.
Вот как обойти эти права доступа для обычных пользователей только для конкретного данного запроса (не применяя галки)?
Примерно как

Dataset.DisableEvents();
Dataset.EnableEvents();

только для прав доступа.

[Шепотом] Рискну предложить создать вьюшку, дать на нее всем права и пользоваться на здоровье...

Показать все комментарии

Подскажите как в одном ShowWarningDialog вывести значения массива списком?
К примеру в таким случае:

        var Arr = new Array();
        var i = 0;
        Dataset.GoToFirst();           
        while (!Dataset.IsEOF) {
        var AccountName = DatasetPhone.Values('AccountName');
        var ContactName = DatasetPhone.Values('ContactName');
       
                Arr[i] = i + ' ' + AccountName;
                i++;
        ShowWarningDialog(i + '. Клиент:' + AccountName + ';
        Dataset.GoToNext();
        }

При этом, чтобы окно ShowWarningDialog открылось один раз со всем списком сразу, а не открывалось по одному разу с одним клиентом.

Нравится

2 комментария
var i = 1;
var AccountList = '';
Dataset.GoToFirst();            
while (!Dataset.IsEOF) {
        var AccountName = Dataset.Values('AccountName');
                AccountList = AccountList +  i + '. Клиент: ' + AccountName +'\r\n';
                i++;
        Dataset.GoToNext();
}
ShowWarningDialog(AccountList);

что то вроде этого подойдет?
ps поправил немного

Да, спасибо, то что надо.

Показать все комментарии

Добрый день!

При рассылке не всегда отрабатывает установка макросных полей в шаблон Outlook. Может быть можно вставить какую-то проверку, чтобы в случае существования #XXXXX# повторно менять тело письма?

Нравится

1 комментарий

Мне кажется лучше поставить отладчик в функцию где макросы заменяются на данные и понять почему в некоторых случаях не находит соответствия...

Показать все комментарии

Подскажите, как передать значение из одного wnd_Window1 в edtEdit.Value в другом окне wnd_Window2 при отсутствии Dataset.

В случае с передачей в Dataset делаю так:

var Attributes = GetNewDictionary();
Attributes("RecordID")            = "{00000000-0000-0000-0000-000000000000}";
Attributes("IsNew")               = true;
Attributes("IsCopy")              = false;
var DefaultValues = GetNewDictionary();
DefaultValues("Source1")       = Control.ParentWindow.Attributes("Source");
ShowEditWindowEx("wnd_Window2", Attributes, DefaultValues);

Нужное значение Control.ParentWindow.Attributes("Source"); передается, т.е. при открытии wnd_Window2 мы видим в поле Source1 наше значение.

Но, как в этом же случае передать значение в edtEdit.Value при отсутствии Dataset?

Нравится

5 комментариев

Attributes("Source1") = Control.ParentWindow.Attributes("Source");

Это будет передача атрибута для окна.
Потом на OnPrepare нового окна ловите его атрибут и пишите значение атрибута в контрол в скрипте

var Source1Value = Self.GetAttribute("Source1");
edtEdit.Value = Source1Value;

Здравствуйте, Alex GF!

Если я правильно понял, то edtEdit - это контрол без привязки к датасету.

Вы можете аналогичным образом передавать в атрибут значение данного поля из первого окна и записывать в аналогичное поле второго окна, только на событии OnPrepare.

"Александр Кудряшов" написал:

Attributes("Source1") = Control.ParentWindow.Attributes("Source");

Это будет передача атрибута для окна.

Потом на OnPrepare нового окна ловите его атрибут и пишите значение атрибута в контрол в скрипте

var Source1Value = Self.GetAttribute("Source1");

edtEdit.Value = Source1Value;


Во втором окне не может определить атрибут:
здесь :

var Source1Value = Self.GetAttribute("Source1");

пишет:
Объект не поддерживает это свойство или метод.

UPD:
А вот таким образом:

var Source1Value = GetAttribute(Self, 'Source1');

Атрибут определился.

Да, либо так:

GetAttribute(Self, "Source1");

либо так

Self.Attributes("Source1");

"Alex GF" написал:Атрибут определился.

Попутал функции, что ж делать.. смысл тот же... живу одновременно в мире кодов трех поколений TS :)

Показать все комментарии