контрагенты
продажи
Продукты
5.x

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

Нравится

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

Добрый день.

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

Если будут вопросы - задавайте.

Показать все комментарии
Технические вопросы
5.x

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

float Val1 = Page.MyControl1Edit.Value;
float Val2 = Page.MyControl2Edit.Value;
Page.MyControl3Edit.Value = Val1*Val2;

не компилируется.

float Val1 = float.Parse(Page.MyControl1Edit.Value.ToString());
float Val2 = float.Parse(Page.MyControl2Edit.Value.ToString());
Page.MyControl3Edit.Value = Val1*Val2;

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

Как написать правильно?

Нравится

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

Лучше берите не значения из контролов, а у DataSource.

Page.DataSource.ActiveRow.GetTypedColumnValue<float>("FieldName");
Page.DataSource.ActiveRow.SetColumnValue("FieldName", value);

Ольга,
спасибо получилось как Вы советуете.

Показать все комментарии
записи реестра
Технические вопросы
5.x

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

Нравится

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

Решал похожую задачу: при клике OK в карточке проверял условие и если оно выполнялось - показывал вопрос пользователю (да или нет). Если да - выполнял некое действие, а затем базовая логика сохранения и закрытия карточки. Если нет - не делал ничего, карточка оставалась открытой.
фрагмент БП
У вас должно быть похоже, но проще. Принимается сообщение нажатия на кнопку, в блоке-скрипте присваивается значение булевскому параметру (его надо создать в дизайнере). Затем два потока, один условный при параметре, равном true, на событие нажатия кнопки в базовом процессе. Другой - по умолчанию (если параметр false) - сообщение пользователю о невозможности удаления и всё.

В скрипте scr_AccountsGridArea событие btnDeleteOnClick необходимо изменить примерно так:

var SelectedIDs = grdData.SelectedIDs;
	var SelectedIDs = grdData.SelectedIDs;
	var SelectedIDsCount = SelectedIDs.Count;
	if (!SelectedIDsCount) {
  		return;
	}
	var deleteflag = true;
	var i;
	for (i = 0; i<SelectedIDsCount; i++) {
		if (GetDatasetFieldValueByID('ds_Account', SelectedIDs([i]), 'StatusID') == StatusIdValue) {
			deleteflag = false;
		}
	}
	if (deleteflag) {
		scr_BaseGridArea.btnDeleteOnClick(Control)
	}
        else {
		ShowInformationDialog('Нельзя удалить действующего контрагента');
	}

Где 'StatusID' - Имя поля Статус, а StatusIdValue - ID статуса "действующий"

Не заметил, что BPM. Но может кому-то понадобится для CRM.

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

При таком подходе, Вы возвращаете серверную подписку на кнопку, в то время, как по умолчанию - клиентская.
Как выход, на событии Init своей страницы, перед вызовом базового обработчика подписаться на событие DataSource.BeforeRemoveRow, выполнить проверку на условие и в случае отрицательного результата такой проверки установить свойство DataSourceEventArgs.Cancel = true; При таком подходе, Вам не придется делать какие-то дополнительные запросы в БД, поскольку аргумент DataSourceEventArgs будет содержать ссылку на удаляемую строку.

Приблизительно будет так:
В скрипте перед вызовом базовой логики пишете:

Page.DataSource.BeforeRemoveRow += (sender, e) => {
var account = e.Row;
if (account == null) {
return;
}
Guid statusId = account.GetTypedColumnValue("StatusId");
if (statusId.Equals(ActiveAccountStatusId)) {
e.Cancel = true; // Это нужно, что не прошло базовое удаление
ErrorMessageText = new LocalizableString("Вы не можете удалить действующего контрагента");
}
};

Где StatusId - название поля статуса в БД, ActiveAccountStatusId - константа действующего статуса контрагента, а ErrorMessageText - локализируемая строка с сообщением (разумеется Вашим :) ).
Потом вставляете Исключающее или с условным потоком в котором проверяете:

!string.IsNullOrEmpty(ErrorMessageText.ToString())

и после которого идет скрипт о сообщении.

Показать все комментарии
Технические вопросы
5.x

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

Что это? И как это можно исправить?

Нравится

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

"Наталия П." написал:Что это? И как это можно исправить?

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

> открыть с сервера, на котором расположено приложение
все и так расположено на моем компьютере... :(

> придется создавать заново
это часа 3 работы (очень огромная таблица с кучей данных, которые надо импортировать).
Понятно, что если другого выхода нет, буду переделывать...

А вообще странно - я же даже не сохранила данные.

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

Показать все комментарии
Технические вопросы
5.x

Солкнулась с неприятной проблемой - ограничение при названии объекта, наследуемого от типа "базовая группа" на 22 символа. При том, что у меня создана уже вся основа базы данных. Заимпортированны данные и воссозданы связи между объектами на уровне SQL.

Есть объект RealEstateAddress. И при попытке создания для него RealEstateAddressFolder получаю ошибку :

При этом, сохранив ...Folder под немного другим именем - AddressFolder, при попытке регистрации рабочего места для RealEstateAddress, я получаю сообщение что необходимо создать RealEstateAddressFolder. Хотя я создала для него AddressFolder. При попытке переназвать сам объект RealEstateAddress, получаю ошибку при компиляции - поле RealEstateAddress не обнаружено в других объектах (которые были связаны с данным объектом).
Какой-то заколдованный круг. В связанных объектах я не могу поменять, пока не сохраню объект. А сохранить объект не могу, потому что обнаруживается ошибка в связанных объектах.
Как быть???

Нравится

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

Добрый день, Наталья!

В данном случае ограничение на количество символов в названии объекта связано с ограничением СУБД. Решением в данное случае будет переименование объекта - ему следует присвоить значение с меньшим количеством символов.

Прошу прощения, но выше я писала, что
При попытке переназвать сам объект RealEstateAddress, получаю ошибку при компиляции - поле RealEstateAddress не обнаружено в других объектах (которые были связаны с данным объектом).

удалить а потом создать заново(может быть в конфигурации он создался а на сервере нет)? кеш почистили?

Удалить что?

объект RealEstateAddress.
А вообще... я не туда полез, не слушайте меня :smile:

Здравствуйте, Наталия!

Переименовывать объекты нельзя - на имя объекта при его создании идет завязка в системе, т.к. имя объекта также является именем таблицы.

В данном случае вам действительно нужно удалить объект и создать его заново.

Показать все комментарии
dll
Технические вопросы
5.x

У меня сборка собственной dll.
Как мне зарегистрировать её в папке BPMOnline, а также что и где прописывать её уже в самих страницах?

Нравится

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

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

Во вложении инструкция.

Вопросы по документу: dobavlenie_ssylki_na_storonnyuyu_sborku_v_konfigruraciyu.docx

По пункту #8. Я могу после выполнения этого действия удалить эту временную (как я понимаю) страницу?

По пункту #9. Как происходит пере генерация страницы?

По пункту #1. Могу ли я не создавать никакого метода, а уже воспользоваться имеющимся?

Максим, здравствуйте.

Да, все верно.

PS: по поводу "перегенерации" не совсем понял, что Вы имеете ввиду.

Я тоже не понял что вы имеете в виду "перегенерация"!?
Как происходит перегенерация страницы описанная в руководстве которую вы подкрепили, вы её читали?

Максим, добрый день.

Пере генерация - это генерация исходного кода (читай компиляция). Т.е. правой кнопкой по схеме - сгенерировать исходный код. В момент компиляции и добавляется ссылка на сборку.

Показать все комментарии
элемент действия
Технические вопросы
5.x

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

Хотела бы спросить на счет элемент действия "Вопрос пользователю". Можно ли настроит "кому адресован этот вопрос" и что случится если закрыт "карточку вопроса" не отвечая на вопросы. На тестовой среде БП останавливался. Можно ли воспроизвести эту карточку вопроса на консоли?

С уважением,
Гюнель

Нравится

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

Здравствуйте, Гюнель!

В случае, если Вами было закрыто окно процесса на этапе Вопрос пользователю, вернуться к процессу можно из реестра Журнал процессов:

processlog

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

Что касается возможности адресовать вопрос конкретному пользователю, подобная функциональность может быть реализована путем создания собственного окна с вопросом, результат работы которого будет передаваться обратно в процесс. Подобная доработка требует программирования и сильно зависит от бизнес-задачи.

Показать все комментарии
Роль
Технические вопросы
5.x

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

Удалила роль "Все сотрудники компании" у одного пользователя. Сейчас хочу, восстановит, но не знаю как. На карточке "Пользователи/ роли (представление)" не могу найти эту роль.

Рабочие места "Инструменты" → раздел " Администрирование: Пользователи" → деталь "Входит в роли"

С уважением,
Гюнель

Нравится

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

Здравствуйте, Гюнель.

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

Для ограничения доступа пользователям Вам следует отбирать лицензии или явно задавать запреты на конкретные объекты/операции/колонки в разделе администрирования доступа.

Показать все комментарии
e-mail
инцидент
карточка редактирования
Технические вопросы
5.x

Пытаюсь действовать по этому блогу
https://community.terrasoft.ru/blogs/9079
Но почти на первом же шаге ошибка. Когда вставляем первый скрипт

var defValuesId = Guid.NewGuid();
var defValues = new Dictionary string, object>();
defValues.Add("Contact", Page.ContactEdit.Value.ToString());
defValues.Add("Account", Page.AccountEdit.Value.ToString());
defValues.Add("Title", Page.TitleEdit.Value.ToString());
var IncidentId = Guid.NewGuid();

UserConnection.UserContext.Add(defValuesId.ToString(), defValues);
var parameters =  
      new Dictionarystring, string> {
            {"createWithUId", IncidentId.ToString()},
                        {"entitySchemaUId", "C449D832-A4CC-4B01-B9D5-8A12C42A9F89"},
                        {"defValuesId", defValuesId.ToString()}
      };
OpenTaskEditPage.OpenerInstanceId = InstanceUId;
OpenTaskEditPage.UseCurrentActivePage = true;
OpenTaskEditPage.PageUId = new Guid("F2BF397B-8FA3-48BA-B691-57360871967A");
OpenTaskEditPage.PageParameters = parameters ;
OpenTaskEditPage.CloseMessage = "IncidentEditPageClosed";

Выдает ошибки:

И во-вторых, где взять ид, которые есть в скрипте
"entitySchemaUId", "C449D832-A4CC-4B01-B9D5-8A12C42A9F89"}
OpenTaskEditPage.PageUId = new Guid("F2BF397B-8FA3-48BA-B691-57360871967A");

Нравится

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

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

По поводу ошибки "Имя OpenTaskEditPage отсутсвует в текущем контексте", в блоге указано (пункт 3), что после создания действия процесса "Открыть страницу", ему следует присвоить наименование. Вы либо не добавили UserTask, либо не так назвали.
А по поводу "UserContext" - какая у Вас версия, не 5.2 случаем?

PS:
ID в принципе вы можете не менять, т.к. это стандартные схемы(окна) и ID У Вас совпадут. А вообще, посмотреть их можно либо запросом в БД, либо в адресной строке, при открытии того или иного окна, указывается также и его идентификатор.

Да, действительно, я слишком поспешил, но по-моему там немного порядок нарушен.
Что касается версии, то 5.4.0.591
После всего остались две ошибки: "UserContext" и еще во втором скрипте (после сигнала IncidentEditPageClosed)

TargetScemaQuery.Filters.Add(TargetScemaQuery.CreateFilterWithParameters(
        FilterComparisonType.Equal, 
        "Id", 
        IncidentId));

используется IncidentId, но в скрипте он до этого не объявлен.

Александр, есть там объявление (в первом листинге):

var IncidentId = Guid.NewGuid();

По поводу UserContext - он был в 5.2. В 5.4 теперь это SessionData. Т.е. по сути Вам нужно заменить

UserConnection.UserContext.Add(defValuesId.ToString(), defValues);

на

UserConnection.SessionData.[defValuesId.ToString()] = defValues;

Если там потом этот ключ где считывается, то код следующий:

var test = Page.UserConnection.SessionData[defValuesId.ToString()];

C "UserContext", т.е. с SessionData получилось.
На счет IncidentId. Она объявлена в первом скрипте, но второй скрипт идет как отдельная функция, т.е. она не видит что происходит в первом скрипте, соответственно не видит объявление IncidentId.
Или я что-то не понимаю? Как можно передать переменную из одного скрипта в другой?

Добрый день.

Здесь, действительно, немного запутана очередность действий.

Логика следующая:

(сигнал нажатия на кнопку) -> (скрипт подготовки действия процесса "открыть карточку") -> (действие процесса открыть карточку) -> (сигнал закрытия карточки инцидента) -> (скрипт генерации номера инцидента).

И действительно - в последнем элементе набор данных "Инцидент" фильтруется по идентификатору только что созданной новой записи, и её присваивается определенный номер.
Т.к. для фильтрации используется переменная, скорее всего, нужно просто создать параметр страницы, и в первом скрипте, после генерации нового идентификатора, инициализировать этот параметр сгенерированным значением:

myParam =  IncidentId;

А в последнем скрипте, вместо IncidentId использовать параметр.

Параметр нужно создать с типом Guid.

Спасибо. Теперь подберусь немного к сути задачи. Мне надо создать именно инцидент (поставил id инцидента и его карточки, все нормально открывается). Что надо сделать, чтобы после нажатия на кнопку "Ок" у инцидента, т.е. инцидент создан в карточке e-mail он добавился в поле инцидент?

Александр, необходимо добавить сроку кода в элементе (скрипт генерации номера инцидента), т.е. в последний скриптовый элемент в рамках добавленной вами логики:

Page.DataSource.ActiveRow.SetColumnValue("IncidentId", myParam);

где myParam - параметр, в котором хранится Id созданного инцидента.

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

Page.IncidentEdit.SetValueAndText(incidentCollection[0].GetTypedColumnValue<Guid>(primaryColumn.Name), incidentCollection[0].GetTypedColumnValue<string>("Number"));

Но скрипт выполняется сразу после открытия окна инцидента, а т.к. запись еще не внесена он не видит эту строку, соответственно ничего не добавляет. Как подождать закрытия окна инцидента?

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

Нужно ждать сигнал, в данном случае IncidentEditPageClosed. Посмотрите, в блоге данный промежуточный обрабатывающий сигнал присутствует.

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

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

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

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

var entitySchemaManager = UserConnection.EntitySchemaManager;
var entitySchema = entitySchemaManager.GetInstanceByName("KnowledgeBaseFile");
var entitySchemaQuery = new EntitySchemaQuery(entitySchemaManager, entitySchema.Name);

var dataColumn = entitySchemaQuery.AddColumn("Data");
entitySchemaQuery.Filters.Add(
        entitySchemaQuery.CreateFilterWithParameters(
                FilterComparisonType.Equal, "KnowledgeBase", new object[] {new Guid("edb71f06-f46b-1410-e980-20cf30b39373")}));
entitySchemaQuery.Filters.Add(
        entitySchemaQuery.CreateFilterWithParameters(
                FilterComparisonType.Equal, "Name", new object[] {FileName.ToString()}));

var entityCollection = entitySchemaQuery.GetEntityCollection(UserConnection);
if (entityCollection.Count > 0) {
        var data = entityCollection[0].GetBytesValue(dataColumn.Name)  as byte[];    
        var response = HttpContext.Current.Response;
        //response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
        //response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", FileName));
        //response.AddHeader("Content-Length", data.Length.ToString());
        //response.BinaryWrite(data);
        Terrasoft.Configuration.PageResponse.Write(response, data, FileName, Terrasoft.Configuration.ContentType.XmlType);
}

return true;

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

Нравится

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

Наталия, вот здесь: http://www.community.terrasoft.ua/forum/topic/9011 (пост 3) я поднимала похожий вопрос, но в средствами бмпОнлайн он, к сожалению, так и не решился...

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

Насколько я понял, Вы хотите добавить кастомные поля в шаблоны для импорта.
Для этого достаточно скачать, отредактировать и залить шаблон из базы знаний:

В объекте поле должно называться также, как в шаблоне.

Ок, спасибо. А как насчет созадния шаблона для импорта для собственных мокулей?
На данном этапе я обошлась импортом данных прямо через SQL, но на будущее хотелось бы знать.

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

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