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

Пожалуйста, помогите решить задачку:

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

Вариант вручную перебрать все записи, естественно, не приветствуется.

Нравится

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

Здравствуйте, Елена!

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

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

Поиск дублей для справочника - это гвозди микроскопом заколачивать.
Тут подойдёт несложный SQL-запрос, аналогичный этому.

Алина, спасибо, думаю, этот вариант подойдет.

Александр, поскольку я не владею SQL, Вашим предложением воспользоваться не смогу :smile:

Еще один момент, есть ли возможность в принципе фильтровать контрагентов по неосновным отраслям?

"Шатная Елена" написал:Александр, поскольку я не владею SQL, Вашим предложением воспользоваться не смогу

А какая используется СУБД?


Еще один момент, есть ли возможность в принципе фильтровать контрагентов по неосновным отраслям?

Можно, если доработать фильтр или создать новый.

СУБД используется, насколько я понимаю, MS SQL

Тогда примерно так. Вот адаптированный для отраслей код:

--основная отрасль
UPDATE "tbl_Account" SET "FieldID" =
     (SELECT top 1 "ID" FROM "tbl_Field" WHERE "tbl_Field"."Name" = 'Нужная отрасль')
WHERE "FieldID" =
     (SELECT top 1 "ID" FROM "tbl_Field" WHERE "tbl_Field"."Name" = 'Ненужная отрасль')
--неосновные отрасли
UPDATE "tbl_AccountIndustry" SET "FieldID" =
     (SELECT top 1 "ID" FROM "tbl_Field" WHERE "tbl_Field"."Name" = 'Нужная отрасль')
WHERE "FieldID" =
     (SELECT top 1 "ID" FROM "tbl_Field" WHERE "tbl_Field"."Name" = 'Ненужная отрасль')

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

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

После выполнения ненужную отрасль можно удалить.

Александр, большое спасибо за информацию, я обязательно передам ее нашим разработчикам.

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

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

Здравствуйте, Елена!

Фильтровать контрагентов по неосновным отраслям можно также начиная с версии 3.4.0 - там есть подобные фильтры в коробочной версии. Для 3.3.2 фильтры можно добавить на уровне конфигурации.

"Шатная Елена" написал:Исходя из вышеописанного, понимаю, что без программистов вопрос по фильтрации контрагентов по доп. отраслям мне не решить.

Для этого нужно в "администраторе Terrasoft" нужно сконструировать нужный фильтр. Не совсем программирование, но лучше силами программистов или поддержки.

А в чём состоит основная задача, в чистке от ненужной отрасли или в доработке для возможности фильтра по дополнительным отраслям? Ведь если настроить такой фильтр и он выдаст несколько десятков результатов, то всё равно придётся менять отрасль вручную.

Основная задача - удаление лишней отрасли. Она уже решена. Вопрос по фильтру возник, как говорится, по ходу, поэтому он не критичен :smile:

"Alimova Anna" написал:Фильтровать контрагентов по неосновным отраслям можно также начиная с версии 3.4.0 - там есть подобные фильтры в коробочной версии.

Анна, при формировании фильтра в разделе Контрагенты Отрасль = нужная отрасль (указанная как неосновная у контрагента Test) не приводит к тому, чтобы в реестре отобразился контрагент Test. Данная операция была произведена в 3.4.0.38.

Может я не там смотрю?

В группе фильтров "Контрагент" фильтр "Отрасли" даёт нужный эффект. Отдельностоящий "Отрасль" - только по карточке. Вот оно как!

Да, действительно, если указать запрос фильтра Контрагент-Отрасли (а не Отрасль, как я делала раньше :confused:), то все контрагенты с искомой отраслью отображаются. И дописывать ничего не нужно :smile:

Александр, спасибо за подсказку :smile:

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

Ситуация состоит в следующем. В отчете FastReport задано стандартное окошко с фильтрами. При запуске отчета один из фильтров по умолчанию принимает значение текущего пользователя системы. Проблема в том, чтобы одним пользователям предоставить возможность редактировать это поле и выбирать/добавлять к отчету другие контакты, а другим пользователям блокировать его как поле "для чтения". Каким образом это можно реализовать?

Нравится

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

Здравствуйте, Константин!

Решить эту задачу можно на уровне конфигурации. Сделать поле недоступным для редактирования можно следующим образом: в скрипте окна фильтрации добавить программный код

edtFieldName.IsEnabled = {условие};

где edtFieldName - название поля в карточке редактирования.

Программный код условия сильно зависит от того, по какому принципу включается разрешение. Например, если разрешено выбирать ответственного только администратору, тогда программный код примет вид:

edtFieldName.IsEnabled = Connector.CurrentUser.IsAdmin;

Спасибо, Анна, за ответ, но как раз в скрипте

edtFieldName.IsEnabled = {условие};

и есть загвоздка. Дело в том что, все фильтры находятся в контейнере IFiltersBuilderControlDataFieldsList, и у элементов этого списка нет такого свойства, как IsEnebled, лишь только Enebled, которое отвечает за активность фильтра (грубо говоря, стоит ли галочка). Возможно, я что-то не так понял и не там смотрю?

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

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

Динамическое окно фильтрации не подерживает возможность делать один из фильтров нередактируемым - это контрол, поведение которого зашито в программном коде.

В данном случае есть два варианта решения:

1. Сделать пользовательское окно фильтрации, и отключать контрол в нем. Эта реализация корректна с точки зрения логики фильтрации;

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

Спасибо большое

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

Недавно столкнулся с задачей отфильтровать контакты по наличию фото.
Реализуется задача путем добавления пользовательского фильтра в сервис sq_Contact.

  1. Находим сервис Contacts\General\Main Grid\sq_Contact и добавляем в его в блок условий WHERE новый Exists Filter

    2.png

  2. Назовите его PhotoExistsFilter

    3.png

  3. В блок FROM добавьте таблицу tbl_Contact, задайте ей псевдоним tbl_ContactPhoto

    4.png

  4. В его блок Select добавьте колоку ID из таблицы tbl_ContactPhoto

    5.png

  5. В блок WHERE из таблицы tbl_Contact AS tbl_ContactPhoto добавьте фильтр сравнения (Compare Filter) c проверкой условия tbl_Contact.ID = tbl_ContactPhoto.ID

    6.png

  6. В этот же блок WHERE из таблицы tbl_Contact AS tbl_ContactPhoto добавьте пользовательский булевский фильтр. Укажите заголовок: Фото есть, Группа - Контакт

    7.png

  7. В блок Select пользовательского булевского фильтра добавьте SQL-колонку CustomSQLColumn с содержанием: (case when Photo is null then 0 else 1 end)

    8.png

  8. В Блоке FROM задайте таблицу tbl_Contact и задайте ей псевдоним ContactPhoto

    9.png

  9. В поcледний блок WHERE добавьте еще один фильтр сравнения:

    10.png

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

    12.png

Нравится

Поделиться

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

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

Нравится

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

Окно настроек предварительной фильтрации данных доступно только для отчетов. Для графиков данный функционал отсутствует.
Задать условие фильтрации данных, используемых для отображения графика, Вы можете в окне свойств графика.

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

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

Хееелп. Помогите, пожалуйста, сделать постоянный фильтр.

Нравится

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

Укажите в свойстве FilterSetCode, основного представления для используемого грида, название Ваше фильтра, только в этом случаи используемый параметр запроса должен быть явно определен.

Спасибо, Олег! То, что надо.

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

Есть деталь, в которой есть такие основные поля: дата, числовой показатель. Хотелось бы сделать представление в детали, в котором отображались эти данные, но сгруппированные по месяцам. То есть с такими полями: период (месяц, год), числовой показатель (сумма всех числовых показателей за указанный месяц).

Нравится

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

Придумал сделать такую выборку:

SELECT
  left(convert(varchar,[Date],112),6),
  sum([Out])
FROM
  [TerraSoft].[dbo].[tbl_Stats]
GROUP BY
  left(convert(varchar,[Date],112),6)

Как действовать дальше?
Ведь поле left(convert(varchar,[Date],112),6) и GROUP BY
left(convert(varchar,[Date],112),6) должны срабатывать только для представления, а в обычном случае:

SELECT
  [Date],
  [Out]
FROM
  [TerraSoft].[dbo].[tbl_Stats]

К тому же как поле left(convert(varchar,[Date],112),6) привести к нормальному виду для пользователя что-то вроде "январь 2010"?

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

Я так и подозревал, что придется создавать новый грид с отдельным запросом и датасетом. Есть пару вопросов для уточнения:
1. По поводу подцепить view в виде сервиса таблицы не нашел (сильно не старался), но интуитивно понял как сделать. Идею http://community.terrasoft.ru/node/3096 поддерживаю!
2. По поводу отображения периода лучше во view сделать или в датасете?
3. По поводу новой странички внутри закладки, это делается аналогично закладкам в деталях?

1. http://community.terrasoft.ua/forum/topic/5455 кратко описал Олег Лабьяк
2. все расчеты во view. на его основе простейший запрос и датасет
3. Как Задачи/расписание например... в принципе много вариантов

Почти получилось. Добавил к окну детали еще один датасет, сделал закладки со страницами, на каждой разместил дата грид, датагридвью с колонками. Обработчики событий для второго датасета установил такие же, как и были уже у автоматически созданного (окно изначально создавалось, как потомок wnd_BaseGridArea). Но почему-то второй датасет не хочет работать. В чем может быть проблема?
Или проще создать окно с нуля?

"Штинов Антон Викторович" написал:Но почему-то второй датасет не хочет работать

на OnPrepare детали повесьте открытие второго датасета

Подробнее можно?
Ведь на OnPrepare детали уже висит обработчик унаследованный от wnd_BaseGridArea

Повесил на onPrepare

function wnd_OrderInProjectsOnPrepare(Window) {
	dlDataByMonth.Dataset.Open();
	ShowInformationDialog('test');
}

Событие срабатывает, но в dataGridView с этим Dataset ничего не отображается.
Пробовал разные варианты. Вывод такой - второй Dataset не имеет данных (((

Добавил

function dlDataByMonthOnDatasetAfterOpen(Dataset) {
	if (Dataset.IsEOF) {
		ShowInformationDialog('empty');
	}
}

выводит "empty", то есть в данном случае dataset оказывается пустым.

Пробовал еще так:

function wnd_OrderInProjectsOnPrepare(Window) {
	var NDataset = Services.GetNewItemByUSI('ds_OrderByMonth');
	NDataset.Open();
	if (NDataset.IsEOF) {
		ShowInformationDialog('empty');
	}  else {
		ShowInformationDialog('ok');
	}
}

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

Антон, Вы смотрели с помощью профайлера, какой запрос отправляется на сервер во время выполнения NDataset.Open()? Возможно, на выборку накладывается дополнительный фильтр.

exec sp_executesql N'SELECT TOP 40
	[vw_OrderByMonth].[Period] AS [Period],
        ...
	[vw_OrderByMonth].[ProjectID] AS [ProjectID]
FROM
	[dbo].[vw_OrderByMonth] AS [vw_OrderByMonth]
WHERE(@P1 = [ProjectID])',N'@P1 varchar(8000)',NULL

Судя по профайлеру не передается параметр. То есть данная деталь должна отображаться для определенного проекта. В выборке параметр ProjectID создан, сравнение с именем ProjectID создано. Для DataGridView установлено свойство FilterSetCode в ProjectID.
Как я понимаю проблема в том, что надо передать параметр ProjectID в датасет. Как это сделать? Догадываюсь, что это надо сделать где-то на одно из событий ProjectWorkspace.

получаем на OnPrepare окна детали (деталь в разделе проекты, правильно?)
var ProjectID = GetAttribute(Self, 'ParentItemID');

фильтруем нужный датасет перед тем как его открыть (фильтр ProjectID и параметр ProjectID есть в запросе?)
ApplyDatasetFilter(your_Dataset, 'ProjectID', ProjectID, true);

Это нужно сделать во время обновления менеджера деталей (функция RefreshDetails скрипта scr_ProjectWorkspace). В функциях инициализации и обновления Вашей детали необходимо учесть ситуацию, когда активной будет второе представление.

Также необходимо устанавливать значение параметра ProjectID во время обработки события OnActiveViewChanged объекта grdData детали. Если изменяется текущее представление, нужно проверить, было ли инициализировано второе представление, и обновить его.

А как из scr_ProjectWorkspace обращатся к элементам окна детали?

Есть необходимость обращаться именно к элементам окна детали? В процессе инициализации обычно происходит присвоение нужных значений атрибутам, а потом эти атрибуты передаются в окно детали, и дальнейшая их обработка происходит уже в скрипте детали. Посмотрите в scr_ProjectWorkspace и других скриптах разделов тексты функций, которые начинаются на Initialize...Detail и Refresh...Detail.

Вообще обратиться из скрипта раздела к любому элементу нужной детали можно так:

Self.ComponentsByName('wnd_...Detail').Window.ComponentsByName(...).

Совсем запутался.
Как советовал Александр Кудряшов, на OnPrepare окна детали делать бесполезно, этот эвент срабатывает только один раз при открытие ТС.
Как я уже понял все действия надо выполнять в scr_ProjectWorkspace в функции RefreshDetails().
Как именно это можно сделать?
добавил туда такой код:

var Dataset = wndOrderDetail.Window.ComponentsByName('dlDataByMonth').Dataset;
ApplyDatasetFilter(Dataset, 'ProjectID', wndOrderDetail.Window.Attributes('ParentItemID'), true);
Dataset.Open();

Работает, но нужно заставить второй датагрид перерисовыватся, после обновления второго датасета. То есть данные показывает только после нажатия кнопки обновить в датагриде. Как это сделать?
А также как отключить датагрид, который создается поумолчанию?

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

"Лабьяк Олег Игоревич" написал:Также необходимо устанавливать значение параметра ProjectID во время обработки события OnActiveViewChanged объекта grdData детали.

Попробуйте обновлять текущий датасет детали в этом обработчике. Сначала определите ID родительской записи (в принципе, если всё реализовано правильно, это значение должно быть в атрибуте ParentItemID), далее закройте текущий датасет реестра (если он открыт), отключите все его фильтры, примените фильтр по родительской записи и откройте датасет.

В общем случае все эти действия выполняет функция RefreshDetailData, которая присутствует практически в любой функции обновления. Но в Вашем случае важно передать в неё именно датасет активного окна. Поэтому я писал ранее:

"Лабьяк Олег Игоревич" написал:В функциях инициализации и обновления Вашей детали необходимо учесть ситуацию, когда активной будет второе представление.

А моё замечание по поводу OnActiveViewChanged касалось ситуации, когда Вы выделили в основном реестре запись, открыли Вашу деталь и заметили, что нужное Вам представление скрыто. В этом случае при переходе на это представление необходимо выполнить его рефреш.

Сделал так (скрипт scr_ProjectWorkspace):

function Initialize() {
...
  // скрыть кнопки и datagrid, которые создаются по умолчанию для окна деталей
  SetAttribute(wndDetail.Window, 'HideButtonsFrame', true);
  wndDetail.Window.ComponentsByName('grdData').IsVisible = false;
  RefreshProject();
}
 
function RefreshDetails() {
  ... else
  if (pcDetails.ActivePage.Name == pgDetail.Name) {
    RefreshCommonDetail(BaseWorkspace, wndDetail, 'ProjectID', 'ProjectID', '', '');
    var Dataset = wndDetail.Window.ComponentsByName('dlDataCustom').Dataset;
    Dataset.Close();
    ApplyDatasetFilter(Dataset, 'ProjectID', wndDetail.Window.Attributes('ParentItemID'), true);
    Dataset.Open();
  }
}

Где dlDataCustom компонент DatasetLink с дополнительной выборкой

Само окно детали (наследуется от wnd_BaseGridArea):
Добавлено две закладки (pages) на каждой по DataGrid, DataGridView с колонками. Одна DataGrid берет данные из dlData (который создается по умолчанию), вторая DataGrid берет данные из dlDataCustom.
Вот таким образом всё работает.

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

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

Нравится

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

Да, возможно. Указанная схема уже работает для полей "город" и "страна" в карточке редактирования контакта и контрагента.

А код реализации возможно увидеть, ибо у нас данная схема в карточке редактирования контагента и контакта не работает.

На событие OnPrepareSelectWindow поля Город.

var LookupDataset = LookupDataControl.DataField.LookupDataset;
var Dataset = dlData.Dataset;
ApplyDatasetFilter(LookupDataset,'StateID', Dataset.Values('StateID'), 
  !IsEmptyValue(Dataset.Values('StateID')));

Подключите скрипт scr_Utils и обратите внимание, что необходим фильтр StateID в sq_City.

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

Добрый день!

Помогите, пожалуйста, решить следующую задачу:
1) В карточку редактирования записи необходимо добавить грид
2) При нажатии кнопки Добавить в этом гриде выводить окно выбора нескольких записей справочника (такое же как при выборе записей справочника в фильтрах разделов)
3) При нажатии на кнопку ОК в этом окошке из п.2 записи добавлять в грид из п.1

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

Нравится

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

Для реализации пункта 2 в обработчике кнопки "Добавить" можно вызывать функцию ShowMultiSelectDataWindow(Dataset, SearchFieldNames, SearchFieldName,
DisplayFieldName, DisplayFieldValues, KeyFieldName, KeyValues, IsReadOnly) из scr_WindowUtils, указав необходимые параметры: источник данных, поля для поиска, для отображения и т.д.

Пункт 3 будет реализован, если создать обработчик события OnNotify для окна реестра в Вашем окне редактирования (если нет отдельного окна реестра - для окна редактирования), а в нём проверять выполнение условия:

	if ((Sender.Name == 'wnd_MultiSelectData') && (Message == MSG_OK)) {
		var ResultIDs = 
			Sender.Attributes('KeyValues').CommaText.split(',');
		........	
	}

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

Спасибо, Олег! Я отпишусь, когда попробую реализовать.

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

В скрипте нужно выбрать записи из ds_InvoiceVises с определенным InvoiceID. Как это можно сделать. В SDK нашел свойство IsFiltered, а вот как указать какой фильтр и какое значение параметра для фильтра?

Нравится

2 комментария
var InvoiceID = 'Needed_GUID'
var ds_InvoiceVises = Services.GetNewItemByUSI('ds_InvoiceItems');
ApplyDatasetFilter(ds_InvoiceVises, 'InvoiceID', InvoiceID, true);
ds_InvoiceVises.Open();

не забудьте в скрипт подключить scr_DB

Попробуйте воспользоваться методом ApplyDatasetIDFilter(Dataset, IDValue, Enabled)из скрипта scr_DB.

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

Добрый день!

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

SELECT * FROM tbl_Account a WHERE
EXISTS (SELECT ID FROM tbl_CampaignAudience ca WHERE
a.ID = ca.AccountID
AND ca.CampaignID IN ('','')

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

Нравится

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

Посмотрите, как реализован в sq_Account фильтр с кодом CompanyGroup.
Вам нужно сделать аналогичный, только вместо tbl_AccountInGroup используйте tbl_Campaign, а вместо ds_AccountGroup в пользовательском Lookup-фильтре - ds_Campaign

Да можно и проще сделать, если я правильно понял:

А, точно, я думал надо по прямой ссылке из воздействия :)

Так не получится, в ds_Campaign нет AccountId. Я использую tbl_CampaignAudience, но все равно не такой запрос,как нужно. Прикладываю сервис, где реализовала этот фильтр, может,кто-то поможет.
Версия 3.3

Дмитрий, спасибо, так заработало! :smile:

Всегда пожалуйста :)

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