Вопрос

Как убрать действие "Удалить" в детали.
Речь идет о кнопках "Копировать/изменить/удалить" во всплывающем окне детали.

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

Прикрепленные файлы
11111.JPG24.69 КБ

У меня такой же вопрос

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

1)

getDeleteRecordMenuItem: Terrasoft.emptyFn //добавлять на схемы деталей (пример OrderProductDetailV2) в блок methods

2) Можно создать кастомную операцию (права доступа на операции) и проверять есть ли у пользователя доступ к этой операции. Пример проверки доступа к операции:

            setUserOperationRightsForCreateChange: function() {
                var operationsToRequest = [];
                debugger;
                operationsToRequest.push("CanCreateChange");
                RightUtilities.checkCanExecuteOperations(operationsToRequest, function(result) {
                    if (result) {
                        this.set("CanCreateChange", result.CanCreateChange);
                    }
                }, this);
            },

А не проще ли права доступа на удаление в конкретном объекте настроить?

Дмитрий А., 
Правильно Вас понял, что при добавлении этого (getDeleteRecordMenuItem: Terrasoft.emptyFn ) в блок methods схемы детали, мы уберем у детали действие удалить?!

А когда вызывать этот метод(getDeleteRecordMenuItem), при каких обстоятельствах?! 

Соломонов Алексей Михайлович,

Посмотрите что делает этот метод в коробке. Он как раз отвечает за добавление пункта меню.

Вызывается в addRecordOperationsMenuItems схемы BaseGridDetailV2

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

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

this.callParent(arguments);

 

Дмитрий А.,
Схема деталей куда добавляем (getDeleteRecordMenuItem: Terrasoft.emptyFn) должна как-то ссылаться на BaseGridDetailV2  ?

 

 

Добавить комментарий

Соломонов Алексей Михайлович,

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

RightUtilities

Пример:

define("ContactSectionV2", ["RightUtilities"], function(RightUtilities) {
 
...
 
}

 

Стандартными методами вы можете запретить удаление из объекта детали для определенных ролей.

Пункт Delete у всех останется, но пользователю будет выдавать сообщение, что для удаления не хватает прав.

Хотя, признаю, пользователям было бы удобнее сразу видеть, что они что-то не смогут сделать (добавить, исправить, удалить...)

Дмитрий А.,
 

Дело как раз в том, что эта деталь и наследуется либо от:
 - Редактируемая деталь документа ( MOBaseSchema )
 - DocumentDetailV2 ( MODocument )

И не имеет ни каких ссылок на BaseGridDetailV2

Так же как и родители.

 

Если логика наличия доступа к действию связана с ролями, то лучше действительно, как посоветовал Владимир, настроить доступ на удаление к объекту этой детали штатными средствами:

scr_section_administering_tab_objects_dtl_operations_access.png

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

Добавить комментарий

Соломонов Алексей Михайлович пишет:
 - Редактируемая деталь документа ( MOBaseSchema )  - DocumentDetailV2 ( MODocument )

А они от чего наследуются? 

Дмитрий А.,

От MODocument, а тот в свою очередь BaseGridDetailV2. С этим благодаря Вам разобрались.

Вы упомянули про проверку.
1)
if (this.$CanManageCaseDetails === true) {
                        this.callParent(arguments);
                    }

2) В свою очередь
this.$CanManageCaseDetails = result.MOCanManageCasePageDetails;

Вы не могли бы пояснить в каких случаях она (1) срабатывает?

Смотрите выше в коде, где result.MOCanManageCasePageDetails заполняют. Название звучит очень похоже на право на операцию у текущего пользователя.

Соломонов Алексей Михайлович,

без полного кода не совсем понимаю о чем речь. 

предлагаю такой вариант:

define("BCSchema1Detail", ["RightUtilities"], function(RightUtilities) {
	return {
		entitySchemaName: "BCPurchasedServices",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		attributes: {
            CanCreateChange: {
                dataValueType: this.Terrasoft.DataValueType.BOOLEAN,
                type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                value: true
            }
		},
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
		methods: {
            init: function() {
                this.callParent(arguments);
                this.setUserOperationRightsForCreateChange();
            },
			setUserOperationRightsForCreateChange: function() {
                var operationsToRequest = [];
                // debugger;
                operationsToRequest.push("CanCreateChange");
                RightUtilities.checkCanExecuteOperations(operationsToRequest, function(result) {
                    if (result) {
                        this.set("CanCreateChange", result.CanCreateChange);
                        console.log(result.CanCreateChange);
                    }
                }, this);
            },
			addRecordOperationsMenuItems: function(toolsButtonMenu) {
				var isDetailEnabled = this.get("IsEnabled");
				if (isDetailEnabled === false) {
					return;
				}
				var copyRecordMenuItem = this.getCopyRecordMenuItem();
				if (copyRecordMenuItem) {
					toolsButtonMenu.addItem(copyRecordMenuItem);
				}
				var editRecordMenuItem = this.getEditRecordMenuItem();
				if (editRecordMenuItem) {
					toolsButtonMenu.addItem(editRecordMenuItem);
				}
				if (this.get("CanCreateChange")) {
					var deleteRecordMenuItem = this.getDeleteRecordMenuItem();
					if (deleteRecordMenuItem) {
						toolsButtonMenu.addItem(deleteRecordMenuItem);
					}
				}
				var recordRightsSetupMenuItem = this.getRecordRightsSetupMenuItem();
				if (recordRightsSetupMenuItem) {
					toolsButtonMenu.addItem(recordRightsSetupMenuItem);
				}
			}
		}
	};
});

Вам надо добавить в Права доступа на операцию новую операцию с именем CanCreateChange. Доступ к этой операции - добавляете нужные роли. Если пользователь попадает в эту роль - увидит кнопку "удалить". Иначе не увидит. После добавления роли нужно перелогиниться.

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

Есть действие по множественному выбору в реестре. 

Проблема в том, что оно должно выполняться для большого кол-ва записей. Если я делаю Действия-Выбрать все, то он мне показывает, например, 4000 записей. Но когда я попадаю в метод обработки действия, то 

var selectedRows = this.get("SelectedRows");
this.showInformationDialog(selectedRows.length.toString());

возвращает кол-во записей, которые отображаются на странице в текущий момент, например, 30. Как мне поймать все записи?

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

Есть пример реализации?

У меня такой же вопрос

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

Для обработки всех записей нужно использовать запросы в БД , для раздела вычитываются 30 записей по странично (те пролистывая вы можете по 30 записей листать) это сделано с целью увеличения производительности

Григорий Чех,это понятно.

Вопрос в том, как пробросить фильтр в запрос, который выбрал пользователь. Т.е. мне не тупо надо все записи в БД обработать, а те, которые выбраны. А до выбора они могут быть отфильтрованы.

Алексей-Карягин,

Тогда листать постранично по 30 записей и обрабатывать

Григорий Чех,

4000 записей? нет уж, спасибо :)

Нужен другой способ.

Однако действие Delete в разделе работает не со страницей, а именно со всеми записями, кстати

 

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

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

Хочу сделать сабж. Окошко выводится, но список пустой. Что я делаю не так?

Метод onPreparePaymentsList не вызывается, кстати. Ошибок в консоли нет.

define("UsrFlip1Page", ["ServiceHelper", "jQuery", "css!UsrFlip1PageCSS"], function(ServiceHelper, jQuery) {
	return {
		entitySchemaName: "UsrFlip",
		attributes: {
			"PaymentVList": {
				dataValueType: Terrasoft.DataValueType.COLLECTION,
				type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				caption: "Платежи",
				name: "PaymentVList",
				isCollection: true
			}
		},
		details: /**SCHEMA_DETAILS*/{
		},
		diff: /**SCHEMA_DIFF*/[
		]/**SCHEMA_DIFF*/,
		methods: {
			init: function() {
				this.callParent(arguments);
				this.set("PaymentVList", this.Ext.create(Terrasoft.Collection));
			},
 
			onEntityInitialized: function() {
				this.callParent(arguments);
				this.set("ActivePayments", null);
				var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", { rootSchemaName: "UsrPayment" });
				esq.addColumn("Id");
				esq.addColumn("UsrBillNumber");
				esq.addColumn("UsrPpNumber");
				esq.addColumn("UsrSum");
				esq.addColumn("UsrType.Name");
				esq.filters.add("filterAuto", this.Terrasoft.createColumnFilterWithParameter(
					this.Terrasoft.ComparisonType.EQUAL, "UsrAuto", this.get("UsrAutoId").value));
				esq.filters.add("filterStatus", this.Terrasoft.createColumnInFilterWithParameters("UsrStatus.Name",
					["Активный", "Не подтвержден"]));
 
				esq.getEntityCollection(function(result) {
					if (result.success) {
						var PaymentItems = {};
						result.collection.each(function(item) {
							PaymentItems[item.get("Id")] = {
								"value": item.get("Id"),
								"displayValue": item.get("UsrBillNumber") + " / " + item.get("UsrPpNumber") +
									" / " + item.get("UsrSum") + " / " + item.get("UsrType.Name")
							};
						}, this);
 
						var list = this.get("PaymentVList");
						list.loadAll(PaymentItems);
					}
				}, this);
			},
 
			getActions: function() {
				var actionMenuItems = this.callParent(arguments);
				actionMenuItems.addItem(this.getActionsMenuItem(
					{
						"Caption": "Уточнение назначения платежа",
						"Tag": "runPaymentCorrection"
					}
				));
				return actionMenuItems;
			},
 
			onPreparePaymentsList: function() {
				debugger;
			},
 
			runPaymentCorrection: function() {
				if (this.get("PaymentVList").getCount() === 0) {
					Terrasoft.showInformation("По данному авто нет активной оплаты!");
					return;
				}
				debugger;
				Terrasoft.showInputBox("Выберите п/п для уточнения", function(button) {
						Terrasoft.showInformation(button);
					}, ["ok", "cancel"], this, {
					name : {
						caption: "Платежи",
						dataValueType: Terrasoft.DataValueType.ENUM,
						className: "Terrasoft.ComboBoxEdit",
						list: {
							bindTo: "PaymentVList"
						},
						prepareList: {
							bindTo: "onPreparePaymentsList"
						},
						isRequired: true
					}
				},
				{
					defaultButton: 0
				});
			}
		},
		rules: {}
	};
});

 

У меня такой же вопрос

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

Маялся уже. Всю голову сломал. Лист не готовится, от вручную указанного кол-ва записей в листе ничего не зависит, "prepareList" не вызывается... Через час плюнул, сделал собственный модуль)

Делал что-то подобное, но через messageBox. Метод в prepareList вызывался (при попытке выбора), как и метод в change.

Тёскин Дмитрий Валерьевич,

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

Алексей-Карягин,

Примера кода, к сожалению, не осталось. Попробовал вчера на досуге ваш код поковырять - действительно не работает. Возможно я использовал какой-то кастомизированный messageBox. Единственное, что заметил - у меня ветки объекта prepareList и change были внутри customConfig.

Алексей, вот кусок кода, который вы можете использовать для вашей задачи. Были рады помочь.

define("ActivityPageV2", [], function() {
return {
entitySchemaName: "Activity",
rules: {},
messages: {},
details: /*SCHEMA_DETAILS/{}/*SCHEMA_DETAILS/,
attributes: {},
methods: {
 
getActions: function() {
var actionMenuItems = this.callParent(arguments);
actionMenuItems.addItem(this.getActionsMenuItem(
{
"Caption": "Тестовое действие",
"Click":
 
{"bindTo": "statusInputBox"}
}
));
return actionMenuItems;
},
 
statusInputBox: function() {
var caption = "Выбор статуса";
this.set("StatusList", new Terrasoft.Collection());
var controls = {
"ActivityStatus": {
dataValueType: Terrasoft.DataValueType.ENUM,
isRequired: true,
caption: "Статус",
value:
 
{ bindTo: "ActivityStatus" }
,
customConfig: {
list:
 
{ bindTo: "StatusList" }
,
prepareList:
 
{ bindTo: "onPrepareStatusList" }
}
}
};
var statusInputBoxHandler = this.statusInputBoxHandler.bind(this);
Terrasoft.utils.inputBox(caption, statusInputBoxHandler,
[Terrasoft.MessageBoxButtons.OK, Terrasoft.MessageBoxButtons.CANCEL],
this, controls);
Terrasoft.each(Terrasoft.MessageBox.controlArray, function(item)
 
{ item.control.bind(this); }
, this);
},
 
onPrepareStatusList: function() {
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery",
 
{ rootSchemaName: "ActivityStatus" }
);
esq.addColumn("Id");
esq.addColumn("Name");
esq.filters.add("finish", Terrasoft.createColumnFilterWithParameter(
Terrasoft.ComparisonType.EQUAL, "Finish", true));
esq.getEntityCollection(function(result) {
if (result.success) {
var items = {};
result.collection.each(function(item) {
items[item.get("Id")] =
 
{ "value": item.get("Id"), "displayValue": item.get("Name") }
;
}, this);
var list = this.get("StatusList");
list.loadAll(items);
}
}, this);
},
 
statusInputBoxHandler: function(tag, data) {
if (Terrasoft.MessageBoxButtons.OK.returnCode === tag) {
if (Ext.isEmpty(data.ActivityStatus.value)) {
this.showInformationDialog("Нужно что-то выбрать", function()
 
{ this.statusInputBox(); }
);
} else
 
{ this.showInformationDialog(data.ActivityStatus.value.displayValue); }
}
}
 
},
diff: /*SCHEMA_DIFF/[]/*SCHEMA_DIFF/
};
});

 

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

Здравствуйте.
BPM sales 7.11.3
Возможно ли создать следующий виджет:

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

3. Виджет не был бы прикреплен к определенной схеме и отображался повсюду.

Как такое, или что-то похожее, можно сделать? 
Приветствуется любая помощь!

 

У меня такой же вопрос

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

Информация о разработке своего виджета есть тут. Но это — для панели итогов. 

В Вашем случае, скорее сего, вместо виджета стоит модифицировать код боковой (LeftPanelTopMenuModule) или верхней (MainHeaderModule) панели и добавить туда вывод нужной информации. 

Или же, если значение числовое, делать ещё одну иконку правой коммуникационной панели (CommunicationPanel) и выводить на неё цифру, подобно количеству писем или звонков.

Зверев Александр, Спасибо! Могли бы вы уточнить где именно стоит делать модификацию, что бы вывести нужную мне информацию?

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

Зверев Александр,

Есть примеры кода или мануал создание подобного?

Например, так в коммуникационную панель добавляется кнопка.

Зверев Александр,

Спасибо за помощь. :)

P.S. Проверьте ЛС.

В версии 7.13 в верхнюю панель добавили надпись с номером версии. Эта логика реализована в схеме MainHeaderSchema, см. упоминания функции _initConfigurationVersion и атрибута ConfigurationVersion.

На init запускается функция, заполняет атрибут. А у надписей caption привязан к его значению.

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

Добрый день, коллеги!

Есть потребность текстовое поле с типом RICH_TEXT сделать автоматически расширяемым с помощью InlineTextEditViewGenerator.generate. Но в данной конфигурации у поля пропадает заголовок, а он нужен

{
	"operation": "merge",
	"name": "Description",
	"values": {
		"contentType": this.Terrasoft.ContentType.RICH_TEXT,
		"generator": "InlineTextEditViewGenerator.generate",
		"labelConfig": {
			"visible": true
		}
	}
}

 

В чем может быть проблема? Или есть другое решение?

У меня такой же вопрос

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

Добрый день!

Генератор InlineTextEditViewGenerator не рассчитан на использование со свойством labelConfig. Вы можете реализовать собственный генератор на его основе, либо использовать стандарную панель форматирования для RICH_TEXT.

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

В начале сентября наша команда успешно завершила проект внедрения новой CRM системы в строительной компании «Интерстрой». Основной поставленной задачей была оптимизация работы отдела продаж и выход на новый уровень качества обслуживания клиентов.

Компания «ИнтерСтрой» на протяжении 14 лет является лидирующим застройщиком в Крыму и г. Севастополе. За это время в эксплуатацию было успешно введено более 40 многоэтажных жилых домов и многоквартирных комплексов в семи городах. Тысячи семей стали счастливыми обладателями надежного жилья и высокодоходных активов. Застройщик полного цикла «ИнтерСтрой» занимает одну из лидирующих позиций среди застройщиков Крыма не случайно. Ведь это надежная компания, целью которой является создание качественных объектов недвижимости, отвечающих самым передовым требованиям и стандартам качества застройки, создавая будущие дома для жителей полуострова Крым и города Севастополь.

Реализация проекта заняла 8 месяцев, начиная со стадии предпроектного обследования до обучения и запуска системы в опытную эксплуатацию.

Итогом совместной работы с командой «ИнтерСтрой» - является увеличение скорости закрытия сделки. Сокращение времени подготовки документов, аналитические инструменты раскрывающие полную картину процессов в департаменте продаж.

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

Компания «ИнтерСтрой» получила новые точки роста, снижение издержек и повышение лояльности клиентов.

Подробности по ссылке на сайте 

Поделиться

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

Добрый день!

 

Необходимо для окна справочного поля переопределить логику кнопки Добавить. Для этого я создала замещающий клиентский модуль LookupPageViewModelGenerator и изменила метод defaultModeActionButtonClick. Но возникла проблема в получении Id текущей записи (из которой происходит открытие справочного поля). Как можно получить Id?

У меня такой же вопрос

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

this.getSelectedRecords();

Id ТЕКУЩЕЙ карточки (из которой был открыт lookup)

С замещением модуля не всё просто.

Возможно, как-то можно получать Id записи из стека прошлых открытых страниц системы, с которым работают при помощи GetHistoryState, ReplaceHistoryState и PushHistoryState.

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

Как на базовую кнопку "СОХРАНИТЬ" повесить доп функции (выполнение пользовательских методов).
Что бы после нажатия на кнопку "СОХРАНИТЬ", в нужных нам полях сначала сгенерировались значения(если эти поля еще не заполнены), и только после этого уже выполнилось сохранение значений карточки.
 

У меня такой же вопрос

6 комментариев
Лучший ответ

Вам нужно в карточке редактирования переопределить метод save. Например:

            save: function() {
              // Здесь будет вызов нужных Вам методов  

              this.callParent(arguments);
            }

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

Автоматическое заполнение можно реализовать либо в бизнес-правиле фильтрации, либо через свойства атрибута dependencies.

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

Вам нужно в карточке редактирования переопределить метод save. Например:

            save: function() {
              // Здесь будет вызов нужных Вам методов  

              this.callParent(arguments);
            }

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

Автоматическое заполнение можно реализовать либо в бизнес-правиле фильтрации, либо через свойства атрибута dependencies.

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

Можно сделать всю логику во встроенном БП объекта, на событии Saving (до момента сохранения) или на Saved (после). Например, вторым способом формируют номер по порядку в некоторых разделах.

А в чем тогда отличие save от onSaved ?

Это разные вещи, функция на клиенте на JS и на сервере на C#.

То что это разные вещи и так понятно. Вопрос в чем конкретно отличие?!

Соломонов Алексей Михайлович,

save - это метод, который вызывает обработчик onSaved события save.

Вот кусок кода из BasePage:

            /**
             * @inheritdoc Terrasoft.BaseEntityPage#save
             * @override
             */
            save: function(config) {
                this.callParent([function() {
                    this.Terrasoft.chain(this.saveDetailsInChain, function() {
                        this.onSaved(this.cardSaveResponse, config);
                        this.cardSaveResponse = null;
                        delete this.cardSaveResponse;
                    }, this);
                }, this]);
            },

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

Помогите разобраться: имею список названий колонок схемы, нужно на уровне Entity их очистить, чтобы гарантировать, что они не будут видны не только в конкретной форме, но и нигде. Предположил, что можно пройтись по GetColumnValueNames(), но для колонок-справочников имена отличаются, типа <имя>Id (Я так понимаю, как в БД), <имя>Value (lookup value из связанной таблицы). Подскажите, как гарантировано и эффективно очистить колонки по имени? Насколько быстрым будет вариант через Entity - Schema - EntitySchemaColumn? Может ли помочь знание не только ColumnName, но и UId?

У меня такой же вопрос

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

Нужно просто настроить запрещающий доступ по колонкам.

Так же вы на уровне можете скрыть поле на уроне Entity (будет существовать в БД, невозможно будет создать колонку с таким же именем и тд), но тогда обращение к нему стандартными методами будет затруднено. Для этого необходимо изменить режим использования 

Запрещающий доступ не подходит, поскольку администрировать нужно по каждой записи отдельно. Сценарий - индивидуальный менеджер видит все по своему контрагенту, любой менеджер - только часть. Может, есть где-то нормальная документация по sdk с комментариями чуть полнее, чем Overloaded :) ?

Вопрос комбинации доступа по записям и полям обсуждался неоднократно, простого решения нет, только доработка.

 

Зверев Александр,

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

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

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

Если у справочной колонки уже есть «Id» как часть названия, то в базе будет, соответственно, «IdId». Но лучше таких названий избегать.

Исправить первый пост не могу, там не <имя>Value, а <имя>Name, что впрочем не принципиально. Принципиально, что о гглупости, или незнанию, или умышленно созданная колонка ContactName не будет отличаться от Contact.Name, а потом такую ошибку черта лысого найдешь.

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

Спасибо, мы все это смотрели, но мы делаем более-менее generic решение, с тем, чтобы оно работало без дополнительных ограничений и не только в момент сдачи, поэтому варианты посмотреть, перечислить явно и т.п. никак не подходят. Нужна или аутентичная процедура получения одного из другого (или хотя бы документированное API, по которому не приходится догадываться, что имеется в виду), или официальній документ о требованиях к именованию, или (что хуже всего) авторитетное утверждение, что єти колонки каждій именует как Бог на душу положит и задача не решается в принципе.

Требования к именованию публиковались ещё во времена 3.Х.

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

Мы так и делаем, правда там хранятся не Id, а UId, и я пытаюсь от имеющихся UId перейти к columnName, которые можно передать в Entity.SetColumnValue. Думал, что нашел, но см. первый пост этой ветки.

Поскольку на https://community.terrasoft.ru/questions/spisok-ne-administriruemyh-kol… никто не отвечает по сути вопроса, я просто пробую другой подход, основная часть задачи решена, а то, что казалось очевидным при беглом взгляде на имеющийся API, оказалось проблемой.

Обычно имена в базе и схеме совпадают, отличие только для справочных. Можно проверять, справочник ли это и затем добавлять или удалять «Id».

Также можно получить в виде JSON метаданные объекта и анализировать их: для каждой  справочной колонки там в соответствующих полях есть тройка названий: для поля-объекта, поля с Guid и поля для отображения. Например, "Type", "TypeId" и "TypeName".

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

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

Можно ли как-то унаследовать правила? Ибо, копи-паста - это как-то не хорошо...

У меня такой же вопрос

3 комментария
Лучший ответ

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

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

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

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

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

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

Алла Савельева,

вот, да, но копипастить не хочется. Может кто из разрабов ответит?

Если стандартными средствами настроить правила не получится, можно делать кодом, привязав им всем «isRequired» к логике какой-либо функции. Например, такой код есть в EmailTemplateUserTaskPropertiesPage.

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